\chapter{MULgraph geometry files}
\label{mulgrids}

\section{Introduction}
The \texttt{mulgrids} library in PyTOUGH contains classes and routines for creating, editing and saving MULgraph geometry files.  It can be imported using the command:

\begin{lstlisting}
  from mulgrids import *
\end{lstlisting}

\section{\texttt{mulgrid} objects}
\index{MULgraph geometry!objects}
\index{MULgraph geometry!creating}
\index{PyTOUGH!classes!\texttt{mulgrid}}

The \texttt{mulgrids} library defines a \texttt{mulgrid} class, used for representing MULgraph geometry files.

\textbf{Example:}

\begin{lstlisting}
geo = mulgrid()
\end{lstlisting}

creates an empty \texttt{mulgrid} object called \texttt{geo}.

\begin{lstlisting}
geo = mulgrid('geom.dat')
\end{lstlisting}

creates a \texttt{mulgrid} object called \texttt{geo} and reads its contents from a file named \texttt{'geom.dat'}.

Printing a \texttt{mulgrid} object (e.g. \texttt{print geo}) displays a summary of information about the grid: how many nodes, columns, layers, blocks and wells it contains, as well as its naming convention and atmosphere type.

A specification of the MULgraph geometry file format can be found in Appendix \ref{geometry_file_format}.

\subsection{Properties}
\index{MULgraph geometry!properties}

The main properties of a \texttt{mulgrid} object are listed in Table \ref{tb:mulgrid_properties}.  Some of these properties are `header' information, corresponding to the data at the start of a MULgraph geometry file (\texttt{type}, \texttt{convention}, \texttt{atmosphere\_type}, \texttt{atmosphere\_volume}, \texttt{atmosphere\_connection} and \texttt{unit\_type}).

The most important properties of a \texttt{mulgrid} object are \texttt{node}, \texttt{column}, \texttt{connection}, \texttt{layer} and \texttt{well}, which are dictionaries of the grid nodes, columns, connections, layers and wells, accessed by name.  For example, grid layer `AA' of a \texttt{mulgrid} object \texttt{geo} can be accessed by \texttt{geo.layer['AA']}.  (The \texttt{nodelist}, \texttt{columnlist}, \texttt{connectionlist}, \texttt{layerlist} and \texttt{welllist} properties offer access to the nodes, columns, connections, layers and wells by index, which is sometimes useful e.g. for looping over all columns in the grid.)

Connections are slightly different from nodes, columns etc. in that they are not named individually.  However, they can be accessed by the names of the columns connected by the connection.  For example, the connection between columns ` 10' and ` 11' in a \texttt{mulgrid} called \texttt{geo} is given by \texttt{geo.connection[' 10',' 11']}.

The elements of these lists and dictionaries are of type \texttt{node}, \texttt{column}, \texttt{connection}, \texttt{layer} and \texttt{well} respectively.  These are additional object classes to represent nodes, columns, connections, layers and wells, defined in the \texttt{mulgrids} library (see section \ref{other_mulgrid_objects}).

\subsubsection{Grid diagnostics}
\index{MULgraph geometry!diagnostics}

A \texttt{mulgrid} object has some properties (and methods) for evaluating its integrity.  The property \texttt{column\_angle\_ratio} returns an \texttt{np.array} of the `angle ratio' for each column (the ratio of largest to smallest interior angles - see section \ref{columnobjects}), a measure of skewness.  The \texttt{column\_side\_ratio} returns an \texttt{np.array} of the `side ratio' for each column (the ratio of largest to smallest side length), a measure of elongation.  These array properties can be plotted using the \texttt{layer\_plot} method (see section \ref{mulgridmethods}) for a graphical overview of grid quality.

There is also a \texttt{connection\_angle\_cosine} property, which returns an \texttt{np.array} of the angle cosine for each connection (the cosine of the angle between a line joining the nodes in the connection and a line joining the centres of the blocks in the connection).  In general it is desirable for these lines to be as close to perpendicular as possible, making the cosines close to zero.

The \texttt{bad\_columns}, \texttt{bad\_layers}, \texttt{missing\_connections}, \texttt{extra\_connections} and \texttt{orphans} properties return actual problems with the grid which should be fixed.  A summary of all these problems is given by the \texttt{check} method (see section \ref{mulgridmethods}).

Blocks at the ground surface that have very small vertical thickness can sometimes cause problems.  The \texttt{min\_surface\_block\_thickness} property gives a tuple containing the minimum surface block thickness and the name of the column in which it occurs.  Thin surface blocks of this type can be eliminated using the \texttt{snap\_columns\_to\_layers()} method.

\subsubsection{Functions for reading data from file}
\label{mulgridreadfunctions}
\index{MULgraph geometry!file format}
\index{MULgraph geometry!reading}

A \texttt{mulgrid} object has a \texttt{read\_function} property which controls how data are read from file.  This property is a dictionary with six keys: `d', `f', `e', `g', `s' and `x', denoting respectively integer, float, exponential, general, string and blank.  Each item in the dictionary is a function which converts a string from the file on disk into the appropriate value.  For example, \texttt{read\_function['f']} converts a string to a floating point value.  By default, the built-in Python \texttt{float} function is used for this (although it is modified slightly so that it returns \texttt{None} if the input string is blank).  There is a dictionary of default reading functions included in PyTOUGH, called \texttt{default\_read\_function}.

However, the user can specify other functions if needed.  In particular, files produced from Fortran programs sometimes have formatting that is not readable by the default functions, if some more exotic Fortran formatting options have been used.   For example, a `d' can also be used to represent an exponent (like `e'), or spaces can be included within a number, or the exponent identifier (e.g. `e') can be omitted.  PyTOUGH includes a second set of reading functions, called \texttt{fortran\_read\_function}, for handling Fortran formatting.  These are slightly slower than the default reading functions.

The reading functions for a \texttt{mulgrid} object can be specified when the object is being created, e.g.:

\begin{lstlisting}
geo = mulgrid('geom.dat', read_function = fortran_read_function)
\end{lstlisting}

\subsubsection{Block ordering schemes}
\label{sec:mulgrid:blockordering}
\index{MULgraph geometry!block ordering}

By default, the blocks in a TOUGH2 grid created from a \texttt{mulgrid} geometry are ordered
by layer, from the atmosphere down to the bottom of the model, with the blocks within
each layer ordered by column (following the ordering of the \texttt{columnlist} property, which
is the same as the column order specified in the geometry file).

It is also possible to sort the blocks according to their geometrical type (8-node hexahedrons
and 6-node wedges, corresponding to 4-node or 3-node columns respectively). This is useful for
exporting the model to Waiwera, which uses the PETSc DMPlex mesh representation, which sorts
cells by cell type in this way.

This can be done by setting the \texttt{block\_order} property of the geometry. This can be set
when the \texttt{mulgrid} object is created or read from file, as an optional parameter, e.g.:

\begin{lstlisting}
geo = mulgrid('geom.dat', block_order = 'dmplex')
\end{lstlisting}

It can also be specified after creation. The \texttt{block\_order} property is a string which can
take the value \textbf{`layer\_column'} for layer/column block ordering, or \textbf{`dmplex'}
if the blocks are to be sorted by geometrical type. It can also take the value \texttt{None}
which gives the default layer/column ordering.

\begin{lstlisting}
geo.block_order = 'layer_column'
\end{lstlisting}

The block ordering scheme can be stored in the MULgraph geometry file, via an integer flag in
the header (see Appendix \ref{geometry_file_format}). This flag is an extension to the original
MULgraph geometry file format. If a \texttt{mulgrid} object is created by reading a file in
which this flag is not present, its \texttt{block\_order} property will be \texttt{None}, in
which case the default layer/column ordering will be used. When a geometry file is read in,
and a block ordering is specified via the \texttt{block\_order} parameter, this will override
any block ordering stored in the file.

\subsubsection{Tilted geometries}
\index{MULgraph geometry!tilting}

Non-horizontal (i.e. tilted) geometries can be constructed by setting the \texttt{mulgrid} properties \texttt{gdcx} and \texttt{gdcy} non-zero. These properties represent the cosines of the angles the x- and y-axes make with the gravity vector. By default they are both zero, giving a horizontal grid. A geometry with \texttt{gdcx} = 1 can be used to construct a 2-D vertical slice grid with a non-layered structure. When a \texttt{t2grid} object is created from a tilted geometry, e.g. using the \texttt{t2grid} \hyperref[sec:t2grid:fromgeo]{fromgeo()} method, only the gravity cosines of the connections are affected (the \texttt{dircos} property of each connection).

\subsubsection{Rotating permeability directions}
\index{MULgraph geometry!permeability directions}

It is possible to rotate the permeability principal directions of a \texttt{mulgrid} object with respect to the coordinate axes- for example, to align permeabilities with a dominant fault direction- by specifying the \texttt{permeability\_angle} property. When a \texttt{t2grid} object is created, e.g. using the \texttt{t2grid} \hyperref[sec:t2grid:fromgeo]{fromgeo()} method, this can change the \texttt{direction} property of each connection.

\index{MULgraph geometry!properties}
\begin{center}
  \begin{longtable}{|l|l|p{75mm}|}
    \hline
    \textbf{Property} & \textbf{Type} & \textbf{Description}\\
    \hline
    \texttt{area} & float & total horizontal area covered by the grid \\
    \texttt{atmosphere\_connection} & float & connection distance to atmosphere blocks\\
    \texttt{atmosphere\_type} & integer & type of atmosphere\\
    \texttt{atmosphere\_volume} & float & volume of atmosphere blocks\\
    \texttt{bad\_columns} & set & columns that do not contain their own centres\\
    \texttt{bad\_layers} & set & layers that do not contain their own centres\\
    \texttt{block\_connection\_name\_index} & dictionary & indices of block connections (by name)\\
    \texttt{block\_connection\_name\_list} & list & names of block connections (by index)\\
    \texttt{block\_name\_index} & dictionary & indices of blocks (by name)\\
    \texttt{block\_name\_list} & list & names of blocks (by index)\\
    \texttt{block\_order} & string & block ordering scheme\\
    \texttt{boundary\_columns} & set & set of columns on the outer boundary of the grid \\
    \texttt{boundary\_nodes} & list & ordered list of nodes on the outer boundary of the grid \\
    \texttt{boundary\_polygon} & list & list of points representing grid boundary (extra colinear points removed) \\
    \texttt{bounds} & list & [bottom left, top right] horizontal bounds of grid\\
    \texttt{centre} & \texttt{np.array} & position of horizontal centre of the grid \\
    \texttt{columnlist} & list & columns (by index, e.g. \texttt{columnlist[23]})\\
    \texttt{column\_angle\_ratio} & \texttt{np.array} & angle ratio for each column\\
    \texttt{column\_side\_ratio} & \texttt{np.array} & side ratio for each column\\
    \texttt{column} & dictionary & columns (by name, e.g. \texttt{column['AA']})\\
    \texttt{connectionlist} & list & connections between columns (by index)\\
    \texttt{connection\_angle\_cosine} & \texttt{np.array} & angle cosines for all connections\\
    \texttt{convention} & integer & naming convention for columns and layers\\
    \texttt{default\_surface} & Boolean  & \texttt{True} if all columns have default surface elevation\\
    \texttt{extra\_connections} & set & connections defined between columns that are not against each other\\
    \texttt{filename} & string  & file name on disk\\
    \texttt{gdcx}, \texttt{gdcy} & float  & cosines of angles x- and y-axes make with gravity vector\\
    \texttt{node\_kdtree} & \texttt{cKDTree} & tree structure for fast searching for nodes \\
    \texttt{layerlist} & list & layers (by index)\\
    \texttt{layer} & dictionary & layers (by name)\\
    \texttt{min\_surface\_block\_thickness} & (float, string) & thickness of thinnest surface block (and associated column name)\\
    \texttt{missing\_connections} & set & missing connections between columns\\
    \texttt{nodelist} & list  & nodes (by index)\\
    \texttt{node} & dictionary  & nodes (by name)\\
    \texttt{num\_atmosphere\_blocks} & integer & number of atmosphere blocks\\
    \texttt{num\_blocks} & integer & total number of blocks in the grid\\
    \texttt{num\_block\_connections} & integer & total number of block connections in the grid\\
    \texttt{num\_columns} & integer & number of columns\\
    \texttt{num\_connections} & integer & number of connections between columns\\
    \texttt{num\_layers} & integer & number of layers\\
    \texttt{num\_nodes} & integer & number of nodes\\
    \texttt{num\_underground\_blocks} & integer & number of non-atmosphere blocks\\
    \texttt{num\_wells} & integer & number of wells\\
    \texttt{orphans} & set & orphaned nodes (nodes not belonging to any column)\\
    \texttt{permeability\_angle} & float & rotation angle (degrees anticlockwise) of first horizontal permeability direction \\
    \texttt{read\_function} & dictionary & dictionary of functions used to read data from file\\
    \texttt{type} & string  & type of geometry (currently only `GENER' supported)\\
    \texttt{unit\_type} & string & distance unit (blank for metres, `FEET' for ft)\\
    \texttt{welllist} & list & wells (by index)\\
    \texttt{well} & dictionary & wells (by name)\\
    \hline
    \caption{Properties of a \texttt{mulgrid} object}
    \label{tb:mulgrid_properties}
  \end{longtable}
\end{center}

\subsection{Methods}
\label{mulgridmethods}

The main methods of a \texttt{mulgrid} object are listed in Table \ref{tb:mulgrid_methods}.  Details of these methods are given below.

\index{MULgraph geometry!methods}
\begin{center}
\begin{longtable}{|l|l|p{70mm}|}
  \hline
  \textbf{Method} & \textbf{Type} & \textbf{Description}\\
  \hline
  \hyperref[sec:mulgrid:add_column]{\texttt{add\_column}} & -- & adds a column to the grid\\ 
  \hyperref[sec:mulgrid:add_connection]{\texttt{add\_connection}} & -- & adds a connection to the grid\\ 
  \hyperref[sec:mulgrid:add_layer]{\texttt{add\_layer}} & -- & adds a layer to the grid\\ 
  \hyperref[sec:mulgrid:add_node]{\texttt{add\_node}} & -- & adds a node to the grid\\ 
  \hyperref[sec:mulgrid:add_well]{\texttt{add\_well}} & -- & adds a well to the grid\\ 
  \hyperref[sec:mulgrid:block_centre]{\texttt{block\_centre}} & \texttt{np.array} & block centre\\
  \hyperref[sec:mulgrid:block_contains_point]{\texttt{block\_contains\_point}} & Boolean & whether a block contains a 3D point\\
  \hyperref[sec:mulgrid:block_mapping]{\texttt{block\_mapping}} & dictionary & mapping from the blocks of another \texttt{mulgrid} object\\
  \hyperref[sec:mulgrid:block_name]{\texttt{block\_name}} & string & name of block at given layer and column\\
  \hyperref[sec:mulgrid:block_name_containing_point]{\texttt{block\_name\_containing\_point}} & string & name of block containing specified point\\
  \hyperref[sec:mulgrid:block_surface]{\texttt{block\_surface}} & float & block top elevation\\
  \hyperref[sec:mulgrid:block_volume]{\texttt{block\_volume}} & float & block volume\\
  \hyperref[sec:mulgrid:check]{\texttt{check}} & Boolean & checks grid for errors (and optionally fixes them)\\ 
  \hyperref[sec:mulgrid:column_boundary_nodes]{\texttt{column\_boundary\_nodes}} & list & nodes around the outer boundary of a group of columns\\ 
  \hyperref[sec:mulgrid:column_bounds]{\texttt{column\_bounds}} & list & bounding rectangle around a list of columns\\ 
  \hyperref[sec:mulgrid:column_containing_point]{\texttt{column\_containing\_point}} & column & column containing specified horizontal point\\ 
  \hyperref[sec:mulgrid:column_mapping]{\texttt{column\_mapping}} & dictionary & mapping from the columns of another \texttt{mulgrid} object\\
  \hyperref[sec:mulgrid:column_name]{\texttt{column\_name}} & string & column name of a block name\\ 
  \hyperref[sec:mulgrid:column_neighbour_groups]{\texttt{column\_neighbour\_groups}} & list & groups connected columns\\ 
  \hyperref[sec:mulgrid:column_quadtree]{\texttt{column\_quadtree}} & quadtree & quadtree structure for searching columns\\ 
  \hyperref[sec:mulgrid:column_surface_layer]{\texttt{column\_surface\_layer}} & \hyperref[layerobjects]{\texttt{layer}} & surface layer for a specified column\\
  \hyperref[sec:mulgrid:column_values]{\texttt{column\_values}} & tuple & values of a variable down a column\\
  \hyperref[sec:mulgrid:columns_in_polygon]{\texttt{columns\_in\_polygon}} & list & columns inside a specified polygon (or rectangle)\\ 
  \hyperref[sec:mulgrid:connects]{\texttt{connects}} & Boolean & whether the grid has a connection between two specified columns\\ 
  \hyperref[sec:mulgrid:copy_layers_from]{\texttt{copy\_layers\_from}} & -- & copies layer structure from another geometry\\ 
  \hyperref[sec:mulgrid:copy_wells_from]{\texttt{copy\_wells\_from}} & -- & copies wells from another geometry\\ 
  \hyperref[sec:mulgrid:decompose_columns]{\texttt{decompose\_columns}} & -- & decomposes columns into triangles and quadrilaterals\\ 
  \hyperref[sec:mulgrid:delete_column]{\texttt{delete\_column}} & -- & deletes a column from the grid\\ 
  \hyperref[sec:mulgrid:delete_connection]{\texttt{delete\_connection}} & -- & deletes a connection from the grid\\ 
  \hyperref[sec:mulgrid:delete_layer]{\texttt{delete\_layer}} & -- & deletes a layer from the grid\\ 
  \hyperref[sec:mulgrid:delete_node]{\texttt{delete\_node}} & -- & deletes a node from the grid\\ 
  \hyperref[sec:mulgrid:delete_orphans]{\texttt{delete\_orphans}} & -- & deletes any orphaned nodes from the grid\\ 
  \hyperref[sec:mulgrid:delete_orphan_wells]{\texttt{delete\_orphan\_wells}} & -- & deletes any orphaned wells from the grid\\ 
  \hyperref[sec:mulgrid:delete_well]{\texttt{delete\_well}} & -- & deletes a well from the grid\\ 
  \hyperref[sec:mulgrid:empty]{\texttt{empty}} & --  & empties contents of grid\\
  \hyperref[sec:mulgrid:export_surfer]{\texttt{export\_surfer}} & -- & exports to various files on disk for visualization in Surfer\\ 
  \hyperref[sec:mulgrid:fit_columns]{\texttt{fit\_columns}} & \texttt{np.array} or dictionary & fits scattered data to column centres\\ 
  \hyperref[sec:mulgrid:fit_surface]{\texttt{fit\_surface}} & -- & fits column surface elevations from data\\ 
  \hyperref[sec:mulgrid:from_amesh]{\texttt{from\_amesh}} & (\hyperref[mulgrids]{\texttt{mulgrid}}, dict) & creates Voronoi geometry from AMESH grid\\ 
  \hyperref[sec:mulgrid:from_gmsh]{\texttt{from\_gmsh}} & \hyperref[mulgrids]{\texttt{mulgrid}} & creates geometry from a \texttt{gmsh} grid\\ 
  \hyperref[sec:mulgrid:layer_containing_elevation]{\texttt{layer\_containing\_elevation}} & layer & layer containing specified vertical elevation\\
  \hyperref[sec:mulgrid:layer_mapping]{\texttt{layer\_mapping}} & dictionary & mapping from the layers of another \texttt{mulgrid} object\\
  \hyperref[sec:mulgrid:layer_name]{\texttt{layer\_name}} & string & layer name of a block name\\ 
  \hyperref[sec:mulgrid:layer_plot]{\texttt{layer\_plot}} & -- & plots a variable over a layer of the grid\\
  \hyperref[sec:mulgrid:line_plot]{\texttt{line\_plot}} & -- & plots a variable along an arbitrary line through the grid\\
  \hyperref[sec:mulgrid:line_values]{\texttt{line\_values}} & tuple & values of a variable along an arbitrary line through the grid\\
  \hyperref[sec:mulgrid:meshio_grid]{\texttt{meshio\_grid}} & tuple & mesh in \texttt{meshio} format\\ 
  \hyperref[sec:mulgrid:minc_array]{\texttt{minc\_array}} & array & values for a particular level in a MINC grid\\ 
  \hyperref[sec:mulgrid:nodes_in_columns]{\texttt{nodes\_in\_columns}} & list & nodes in a specified list of columns\\ 
  \hyperref[sec:mulgrid:nodes_in_polygon]{\texttt{nodes\_in\_polygon}} & list & nodes inside a specified polygon (or rectangle)\\ 
  \hyperref[sec:mulgrid:node_nearest_to]{\texttt{node\_nearest\_to}} & \hyperref[nodeobjects]{\texttt{node}} & node nearest to a specified point\\ 
  \hyperref[sec:mulgrid:optimize]{\texttt{optimize}} & -- & adjusts node positions to optimize grid quality\\
  \hyperref[sec:mulgrid:polyline_values]{\texttt{polyline\_values}} & tuple & values of a variable along an arbitrary polyline through the grid\\
  \hyperref[sec:mulgrid:read]{\texttt{read}} & \hyperref[mulgrids]{\texttt{mulgrid}} & reads geometry file from disk\\
  \hyperref[sec:mulgrid:rectangular]{\texttt{rectangular}} & \hyperref[mulgrids]{\texttt{mulgrid}} & creates rectangular grid\\
  \hyperref[sec:mulgrid:reduce]{\texttt{reduce}} & -- & reduces a grid to contain only specified columns\\
  \hyperref[sec:mulgrid:refine]{\texttt{refine}} & -- & refines specified columns in the grid\\
  \hyperref[sec:mulgrid:refine_layers]{\texttt{refine\_layers}} & -- & refines specified layers in the grid\\
  \hyperref[sec:mulgrid:rename_column]{\texttt{rename\_column}} & Boolean & renames a column\\
  \hyperref[sec:mulgrid:rename_layer]{\texttt{rename\_layer}} & Boolean & renames a layer\\
  \hyperref[sec:mulgrid:rotate]{\texttt{rotate}} & -- & rotates a grid in the horizontal plane\\
  \hyperref[sec:mulgrid:slice_plot]{\texttt{slice\_plot}} & -- & plots a variable over a vertical slice through the grid\\
  \hyperref[sec:mulgrid:snap_columns_to_layers]{\texttt{snap\_columns\_to\_layers}} & -- & snaps column surfaces to layer bottoms\\
  \hyperref[sec:mulgrid:snap_columns_to_nearest_layers]{\texttt{snap\_columns\_to\_nearest\_layers}} & -- & snaps column surfaces to nearest layer elevations \\
  \hyperref[sec:mulgrid:split_column]{\texttt{split\_column}} & Boolean & splits a quadrilateral column into two triangles\\ 
  \hyperref[sec:mulgrid:translate]{\texttt{translate}} & -- & moves a grid by simple translation in 3D\\
  \hyperref[sec:mulgrid:well_values]{\texttt{well\_values}} & tuple & values of a variable down a well\\
  \hyperref[sec:mulgrid:write]{\texttt{write}} & -- & writes to geometry file on disk\\
  \hyperref[sec:mulgrid:write_bna]{\texttt{write\_bna}} & -- & writes to Atlas BNA file on disk\\ 
  \hyperref[sec:mulgrid:write_exodusii]{\texttt{write\_exodusii}} &  -- & writes to ExodusII file on disk\\
  \hyperref[sec:mulgrid:write_mesh]{\texttt{write\_mesh}} &  -- & writes to mesh file (various formats) on disk\\
  \hyperref[sec:mulgrid:write_vtk]{\texttt{write\_vtk}} &  -- & writes to VTK file on disk\\
  \hline
  \caption{Methods of a \texttt{mulgrid} object}
  \label{tb:mulgrid_methods}
\end{longtable}
\end{center}

\begin{snugshade}\subsubsection{\texttt{add\_column(\emph{col})}}\end{snugshade}
\label{sec:mulgrid:add_column}
\index{MULgraph geometry!adding!columns}
\index{MULgraph geometry!columns!adding}

Adds a \hyperref[columnobjects]{\texttt{column}} object \texttt{col}
to the grid. If a column with the same name already exists, no new
column is added.

\begin{snugshade}\subsubsection{\texttt{add\_connection(\emph{con})}}\end{snugshade}
\label{sec:mulgrid:add_connection}
\index{MULgraph geometry!adding!connections}
\index{MULgraph geometry!connections!adding}

Adds a \hyperref[connectionobjects]{\texttt{connection}} object
\texttt{con} to the grid. If a connection with the same name already
exists, no new connection is added.

\begin{snugshade}\subsubsection{\texttt{add\_layer(\emph{lay})}}\end{snugshade}
\label{sec:mulgrid:add_layer}
\index{MULgraph geometry!adding!layers}
\index{MULgraph geometry!layers!adding}

Adds a \hyperref[layerobjects]{\texttt{layer}} object \texttt{lay} to
the grid. If a layer with the same name already exists, no new layer
is added.

\begin{snugshade}\subsubsection{\texttt{add\_node(\emph{n})}}\end{snugshade}
\label{sec:mulgrid:add_node}
\index{MULgraph geometry!adding!nodes}
\index{MULgraph geometry!nodes!adding}

Adds a \hyperref[nodeobjects]{\texttt{node}} object \texttt{n} to the
grid. If a node with the same name already exists, no new node is
added.

\begin{snugshade}\subsubsection{\texttt{add\_well(\emph{w})}}\end{snugshade}
\label{sec:mulgrid:add_well}
\index{MULgraph geometry!adding!wells}
\index{MULgraph geometry!wells!adding}

Adds a \hyperref[wellobjects]{\texttt{well}} object \texttt{w} to the
grid. If a well with the same name already exists, no new well is
added.

\begin{snugshade}\subsubsection{\texttt{block\_contains\_point(\emph{blockname}, \emph{pos})}}\end{snugshade}
\label{sec:mulgrid:block_contains_point}
\index{MULgraph geometry!finding!blocks}
\index{MULgraph geometry!blocks!finding}

Returns \texttt{True} if the grid block with the given name contains the 3D point \texttt{pos}.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{blockname}: string\\
  The name of the block.
\item \textbf{pos}: \texttt{np.array}\\
  3-element array representing the 3D point.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{block\_centre(\emph{lay}, \emph{col})}}\end{snugshade}
\label{sec:mulgrid:block_centre}
\index{MULgraph geometry!blocks!centres}

Returns the centre of the block corresponding to the given layer and column.

The horizontal centre is given by the column centre. The vertical centre is given by the layer centre, except for surface blocks with column surface lower than the layer top, in which case it is the midpoint between the column surface and the layer bottom.  (For surface blocks with column surface higher than the layer top, the vertical centre is still the layer centre, to give a uniform pressure reference.)

\textbf{Parameters:}
\begin{itemize}
\item \textbf{lay}: \hyperref[layerobjects]{\texttt{layer}} or string\\
  The specified layer or layer name.
\item \textbf{col}: \hyperref[columnobjects]{\texttt{column}} or string\\
  The specified column or column name.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{block\_mapping(\emph{geo}, \emph{column\_mapping}=\texttt{False})}}\end{snugshade}
\label{sec:mulgrid:block_mapping}

Returns a dictionary mapping each block name in the \texttt{mulgrid} object \texttt{geo} to the name of the nearest block in the object's own geometry.  Can optionally also return the associated column mapping.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{geo}: \hyperref[mulgrids]{\texttt{mulgrid}}\\
  The \texttt{mulgrid} object to create a block mapping from.
\item \textbf{column\_mapping}: Boolean\\
  If \texttt{True}, the column mapping will also be returned (i.e. the function will return a tuple containing the block mapping and the column mapping).  Default value is \texttt{False}.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{block\_name(\emph{layer\_name}, \emph{column\_name}, \emph{blockmap} = \{\})}}\end{snugshade}
\label{sec:mulgrid:block_name}
\index{MULgraph geometry!blocks!names}
\index{MULgraph geometry!names!of blocks}

Gives the name of the block corresponding to the specified layer and column names, according to the naming convention of the grid.

An optional block name mapping can be applied.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{layer\_name}, \textbf{column\_name}: string\\
  Name of layer and column (the widths of these strings are determined by the grid's naming convention).
\item \textbf{blockmap}: dictionary\\
  Dictionary mapping the block names in the geometry to another block naming system. This dictionary need not contain entries for all blocks in the geometry- those not included in the mapping will not be altered.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{block\_name\_containing\_point(\emph{pos}, \emph{qtree}=None, \emph{blockmap}=\{\})}}\end{snugshade}
\label{sec:mulgrid:block_name_containing_point}
\index{MULgraph geometry!finding!blocks}
\index{MULgraph geometry!blocks!finding}
\index{MULgraph geometry!columns!quadtrees}
\index{quadtrees}

Gives the name of the block containing a specified 3-D position in the grid (returns \texttt{None} if the point lies outside the grid).

\textbf{Parameters:}
\begin{itemize}
\item \textbf{pos}: \texttt{np.array}\\
  Position of point in 3-D
\item \textbf{qtree}: \texttt{quadtree}\\
  Quadtree object for fast searching of grid columns (can be constructed using the \hyperref[sec:mulgrid:column_quadtree]{\texttt{column\_quadtree()}} method).
\item \textbf{blockmap}: dictionary\\
  Dictionary mapping the block names in the geometry to another block naming system.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{block\_surface(\emph{lay}, \emph{col})}}\end{snugshade}
\label{sec:mulgrid:block_surface}
\index{MULgraph geometry!blocks!surfaces}

Returns the elevation of the top surface of the block corresponding to the given layer and column.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{lay}: \hyperref[layerobjects]{\texttt{layer}}\\
  The specified layer.
\item \textbf{col}: \hyperref[columnobjects]{\texttt{column}}\\
  The specified column.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{block\_volume(\emph{lay}, \emph{col})}}\end{snugshade}
\label{sec:mulgrid:block_volume}
\index{MULgraph geometry!blocks!volumes}

Returns the volume of the block corresponding to the given layer and column.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{lay}: \hyperref[layerobjects]{\texttt{layer}}\\
  The specified layer.
\item \textbf{col}: \hyperref[columnobjects]{\texttt{column}}\\
  The specified column.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{check(\emph{fix}=False,\emph{silent}=False)}}\end{snugshade}
\label{sec:mulgrid:check}
\index{MULgraph geometry!checking}
\index{checking!MULgraph geometry}

Checks a grid for errors and optionally fixes them.  Errors checked for are: missing connections, extra connections, orphaned nodes, and columns and layers that do not contain their own centres.  Returns \texttt{True} if no errors were found, and \texttt{False} otherwise.  If \texttt{fix} is \texttt{True}, any identified problems will be fixed.  If \texttt{silent} is \texttt{True}, there is no printout (only really useful if \texttt{fix} is \texttt{True}).

\textbf{Parameters:}
\begin{itemize}
\item \textbf{fix}: Boolean\\
  Whether to fix any problems identified.
\item \textbf{silent}: Boolean\\
  Whether to print out feedback or not.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{column\_boundary\_nodes(\emph{columns})}}\end{snugshade}
\label{sec:mulgrid:column_boundary_nodes}
\index{MULgraph geometry!nodes!finding}
\index{MULgraph geometry!finding!nodes}

Returns the nodes around the outer boundary of a list of columns.  The list is ordered, in a counter-clockwise direction.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{columns}: list\\
  The list of columns for which the boundary is required.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{column\_bounds(\emph{columns})}}\end{snugshade}
\label{sec:mulgrid:column_bounds}

Returns a bounding rectangle around a list of columns.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{columns}: list\\
  The list of columns for which the bounds are required.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{column\_containing\_point(\emph{pos}, \emph{columns}=None, \emph{guess}=None, \emph{bounds}=None,\\
\emph{qtree}=None)}}\end{snugshade}
\label{sec:mulgrid:column_containing_point}
\index{MULgraph geometry!finding!columns}
\index{MULgraph geometry!columns!finding}
\index{MULgraph geometry!columns!quadtrees}
\index{quadtrees}

Returns the grid column containing the specified horizontal point.  If \texttt{columns} is specified, only columns in the given list will be searched.  An initial \texttt{guess} column can optionally be specified.  If \texttt{bounds} is specified, points outside the given polygon will always return \texttt{None}.  A quadtree structure can also be specified to speed up searching.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{pos}: \texttt{np.array}\\
  Horizontal position (\emph{x}, \emph{y})
\item \textbf{columns}: list of \hyperref[columnobjects]{\texttt{column}} (or \texttt{None})\\
  List of columns to search.  If \texttt{None}, the entire grid will be searched.
\item \textbf{guess}: \hyperref[columnobjects]{\texttt{column}} (or \texttt{None})\\
  Guess of required column.  If specified, this column will be tested first, followed (if necessary) by its neighbours; only if none of these contain the point will the remaining columns be searched.  This can speed up the process if data follow a sequential pattern in space, e.g. a grid or lines.
 \item \textbf{bounds}: list of \texttt{np.array} (or \texttt{None})\\
  Polygon or rectangle representing e.g. the boundary of the grid: points outside this polygon will always return \texttt{None}.  If the polygon has only two points, it will be interpreted as a rectangle [bottom left, top right].
 \item \textbf{qtree}: \texttt{quadtree} \\
   A quadtree object for searching the columns of the grid.  If many points are to be located, this option can speed up the search.  The quadtree can be constructed before searching using the \hyperref[sec:mulgrid:column_quadtree]{\texttt{column\_quadtree()}} method.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{column\_mapping(\emph{geo})}}\end{snugshade}
\label{sec:mulgrid:column_mapping}

Returns a dictionary mapping each column name in the \texttt{mulgrid} object \texttt{geo} to the name of the nearest column in the object's own geometry.  If the SciPy library is available, a KDTree structure is used to speed searching.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{geo}: \hyperref[mulgrids]{\texttt{mulgrid}}\\
  The \texttt{mulgrid} object to create a column mapping from.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{column\_name(\emph{block\_name})}}\end{snugshade}
\label{sec:mulgrid:column_name}
\index{MULgraph geometry!columns!names}
\index{MULgraph geometry!names!of columns}

Gives the name of the column corresponding to the specified block name, according to the naming convention of the grid.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{block\_name}: string\\
  Block name.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{column\_neighbour\_groups(\emph{columns})}}\end{snugshade}
\label{sec:mulgrid:column_neighbour_groups}

From the given list or set of columns, finds sets of columns that are connected together, and returns a list of them.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{columns}: list or set\\
  List or set of columns to group.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{column\_quadtree(\emph{columns}=None)}}\end{snugshade}
\label{sec:mulgrid:column_quadtree}
\index{MULgraph geometry!columns!quadtrees}
\index{PyTOUGH!classes!\texttt{quadtree}}
\index{quadtrees}

Returns a quadtree structure for fast searching of grid columns, to find which column a given point lies in.  This can then be passed into various other \texttt{mulgrid} methods that do such searching, e.g. \hyperref[sec:mulgrid:block_name_containing_point]{\texttt{block\_name\_containing\_point()}} or \hyperref[sec:mulgrid:well_values]{\texttt{well\_values()}}, to speed them up (useful for large grids).

The quadtree is an instance of a \texttt{quadtree} class, defined in the \texttt{mulgrids} module.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{columns}: list (or \texttt{None})\\
  A list of columns in the grid, specifying the search area.  This parameter can be used to further speed searching if it is only necessary to search columns in a defined area.  If \texttt{None}, the search area is the whole grid (all columns).
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{column\_surface\_layer(\emph{col})}}\end{snugshade}
\label{sec:mulgrid:column_surface_layer}
\index{MULgraph geometry!columns!surface elevation}

Returns the layer containing the surface elevation of a specified column.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{col}: \hyperref[columnobjects]{\texttt{column}}\\
  The column for which the surface layer is to be found.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{column\_values(\emph{col}, \emph{variable}, \emph{depth} = False)}}\end{snugshade}
\label{sec:mulgrid:column_values}
\index{MULgraph geometry!values!down a column}

Returns values of a specified variable down a specified column.  The variable can be a list or \texttt{np.array} containing a value for every block in the grid.

The routine returns a tuple of two arrays (\texttt{d},\texttt{v}), the first (\texttt{d}) containing the elevation (or depth from surface if the \texttt{depth} parameter is set to \texttt{True}), and the second (\texttt{v}) containing the value of the variable at each block in the column.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{col}: \hyperref[columnobjects]{\texttt{column}} or string\\
  The column for which values are to be found.
\item \textbf{variable}: list (or \texttt{np.array})\\
  Values of variable, of length equal to the number of blocks in the grid.
\item \textbf{depth}: Boolean\\
  Set to \texttt{True} to give depths from surface, instead of elevations, as the first returned array.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{columns\_in\_polygon(\emph{polygon})}}\end{snugshade}
\label{sec:mulgrid:columns_in_polygon}
\index{MULgraph geometry!finding!columns}
\index{MULgraph geometry!columns!finding}

Returns a list of all columns with centres inside the specified polygon or rectangle.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{polygon}: list (of \texttt{np.array})\\
  List of points defining the polygon (each point is a two-element \texttt{np.array}).  If the list has only two points, it will be interpreted as a rectangle [bottom left, top right].
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{connects(\emph{column1, column2})}}\end{snugshade}
\label{sec:mulgrid:connects}

Returns \texttt{True} if the geometry contains a connection connecting the two specified columns.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{column1, column2}: \hyperref[columnobjects]{\texttt{column}}\\
  Two columns in the geometry.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{copy\_layers\_from(\emph{geo})}}\end{snugshade}
\label{sec:mulgrid:copy_layers_from}

Copies the layer structure from the geometry \texttt{geo} (deleting any existing layers first).

\textbf{Parameters:}
\begin{itemize}
\item \textbf{geo}: \hyperref[mulgrids]{\texttt{mulgrid}}\\
  The geometry to copy layers from.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{copy\_wells\_from(\emph{geo})}}\end{snugshade}
\label{sec:mulgrid:copy_wells_from}

Copies the wells from the geometry \texttt{geo} (deleting any existing wells first).

\textbf{Parameters:}
\begin{itemize}
\item \textbf{geo}: \hyperref[mulgrids]{\texttt{mulgrid}}\\
  The geometry to copy wells from.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{decompose\_columns(\emph{columns} = [], \emph{mapping} = False, \emph{chars} = ascii\_lowercase)}}\end{snugshade}
\label{sec:mulgrid:decompose_columns}
\index{MULgraph geometry!columns!decomposing}

Decomposes columns with more than four sides into triangular and quadrilateral columns. This can be useful when carrying out calculations on the geometry that rely on finite element methods (e.g. the \texttt{fit\_columns()} method uses it).

In general, columns are decomposed by adding a node at the column centroid and forming triangles around it. However, there are special cases for columns with lower numbers of sides (less than 9) and `straight' nodes, i.e. nodes on a straight line between their neighbouring nodes in the column). These make use of simpler decompositions.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{columns}: list\\
  List of columns to be decomposed. If the list is empty (the default), all columns are decomposed.
\item \textbf{mapping}: Boolean\\
  If \texttt{True}, return a dictionary mapping each original column name to a list of decomposed columns that replace it.
\item \textbf{chars}: string\\
  Specifies a string of characters to use when forming new node and column names.  Default is lowercase letters.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{delete\_column(\emph{colname})}}\end{snugshade}
\label{sec:mulgrid:delete_column}
\index{MULgraph geometry!deleting!columns}
\index{MULgraph geometry!columns!deleting}

Deletes the column with the specified name from the grid.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{colname}: string\\
  Name of the column to be deleted.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{delete\_connection(\emph{colnames})}}\end{snugshade}
\label{sec:mulgrid:delete_connection}
\index{MULgraph geometry!deleting!connections}
\index{MULgraph geometry!connections!deleting}

Deletes the connection between the specified columns from the grid.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{colnames}: tuple of string\\
  Tuple of two column names.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{delete\_layer(\emph{layername})}}\end{snugshade}
\label{sec:mulgrid:delete_layer}
\index{MULgraph geometry!deleting!layers}
\index{MULgraph geometry!deleting!layers}

Deletes the layer with the specified name from the grid.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{layername}: string\\
  Name of the layer to be deleted.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{delete\_node(\emph{nodename})}}\end{snugshade}
\label{sec:mulgrid:delete_node}
\index{MULgraph geometry!deleting!nodes}
\index{MULgraph geometry!nodes!deleting}

Deletes the node with the specified name from the grid.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{nodename}: string\\
  Name of the node to be deleted.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{delete\_orphans()}}\end{snugshade}
\label{sec:mulgrid:delete_orphans}
\index{MULgraph geometry!deleting!nodes}
\index{MULgraph geometry!nodes!deleting}

Deletes any orphaned nodes (those not belonging to any column) from the grid.

\begin{snugshade}\subsubsection{\texttt{delete\_orphan\_wells()}}\end{snugshade}
\label{sec:mulgrid:delete_orphan_wells}
\index{MULgraph geometry!deleting!wells}
\index{MULgraph geometry!wells!deleting}

Deletes any orphaned wells (those with wellheads outside the grid).

\begin{snugshade}\subsubsection{\texttt{delete\_well(\emph{wellname})}}\end{snugshade}
\label{sec:mulgrid:delete_well}
\index{MULgraph geometry!deleting!wells}
\index{MULgraph geometry!wells!deleting}

Deletes the well with the specified name from the grid.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{layername}: string\\
  Name of the layer to be deleted.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{empty()}}\end{snugshade}
\label{sec:mulgrid:empty}
\index{MULgraph geometry!emptying}

Empties the grid of all its nodes, columns, layers, wells and connections.  Other properties are unaffected.

\begin{snugshade}\subsubsection{\texttt{export\_surfer(\emph{filename}='', \emph{aspect}=8.0, \emph{left}=0.0)}}\end{snugshade}
\label{sec:mulgrid:export_surfer}
\index{MULgraph geometry!exporting}

Exports the grid to files on disk useful for visualization in Surfer.  Six files are written out:

\begin{itemize}
\item an Atlas BNA file (\texttt{filename.bna}) representing the grid columns
\item a CSV file (\texttt{filename\_column\_names.csv}) containing the column names
\item a Golden Software blanking file (\texttt{filename\_layers.bln}) file representing the grid layers
\item a CSV file (\texttt{filename\_layer\_bottom\_elevations.csv}) containing the bottom elevations of the layers
\item a CSV file (\texttt{filename\_layer\_centres.csv}) containing the elevations of the centres of the layers
\item a CSV file (\texttt{filename\_layer\_names.csv}) containing the names of the layers
\end{itemize}

\textbf{Parameters:}
\begin{itemize}
\item \textbf{filename}: string\\
  Base name for the exported files.  If it is not specified, the \texttt{filename} property of the \texttt{mulgrid} object itself is used (unless this is also blank, in which case a default name is used), with its extension removed.
\item \textbf{aspect}: float\\
  Aspect ratio for the layer plot, so that the width is the total height of the grid divided by \texttt{aspect} (default 8.0).
\item \textbf{left}: float\\
  Coordinate value of the left hand side of the layer plot (default zero).
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{fit\_columns(\emph{data}, \emph{alpha}=0.0, \emph{beta}=0.0, \emph{columns}=[], \emph{min\_columns}=[], \\
    \emph{grid\_boundary}=False, \emph{silent}=False, \emph{output\_dict}=False)}}\end{snugshade}
\label{sec:mulgrid:fit_columns}
\index{MULgraph geometry!fitting data to columns}
\index{MULgraph geometry!columns!fitting data}

Fits scattered data to column centres, using bilinear least-squares finite element fitting with Sobolev smoothing.  Smoothing is useful when data density is low in some areas of the grid, in which case least-squares fitting without smoothing can fail (e.g. if there are any columns which do not contain any data points).

By default, this method returns an \texttt{np.array} with length given by the number of columns to be fitted. Each value in the array represents the fitted data value at the centre of the corresponding column. If the \texttt{output\_dict} parameter is set to \texttt{True}, a dictionary is returned, with fitted values indexed by column names.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{data}: \texttt{np.array}\\
  Two-dimensional array of data to fit.  Each row of the array should contain the x,y co-ordinates for each data point, followed by the corresponding data value.  Such an array can be conveniently read from a text file using the \texttt{np.loadtxt()} method.
\item \textbf{alpha}: float\\
  Smoothing parameter for first derivatives - increasing its value results in solutions with lower gradients (but may result in extrema being smoothed out).
\item \textbf{beta}: float\\
  Smoothing parameter for second derivatives - increasing its value results in solutions with lower curvature.
\item \textbf{columns}: list of string or \hyperref[columnobjects]{\texttt{column}}\\
  Columns, or names of columns to be fitted.  If empty (the default), then all columns will be fitted.
\item \textbf{min\_columns}: list of string or \hyperref[columnobjects]{\texttt{column}}\\
  Columns, or names of columns for which fitted data will be determined from the minimum of the fitted nodal values (fitted values at all other columns are determined from the average of the fitted nodal values).
\item \textbf{grid\_boundary}: Boolean\\
  If \texttt{True}, test each data point first to see if it lies inside the boundary polygon of the grid.  This can speed up the fitting process if there are many data points outside the grid, and the grid has a simple boundary (e.g. a rectangle).  In general if there are many data points outside the grid, it is best to clip the data set before fitting, particularly if it is to be used more than once.
\item \textbf{silent}: Boolean\\
  Set to \texttt{True} to suppress printing fitting progress.
\item \textbf{output\_dict}: Boolean\\
  Set \texttt{True} to return results as a dictionary of fitted values indexed by column names, instead of an array.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{fit\_surface(\emph{data}, \emph{alpha}=0.0, \emph{beta}=0.0, \emph{columns}=[], \emph{min\_columns}=[], \\
    \emph{grid\_boundary}=False, \emph{layer\_snap}=0.0, \emph{silent}=False)}}\end{snugshade}
\label{sec:mulgrid:fit_surface}
\index{MULgraph geometry!fitting surface elevations}
\index{MULgraph geometry!columns!surface elevation}

Fits column surface elevations from data, using bilinear least-squares finite element fitting with Sobolev smoothing (using the \hyperref[sec:mulgrid:fit_columns]{\texttt{fit\_columns()}} method).  Smoothing is useful when data density is low in some areas of the grid, in which case least-squares fitting without smoothing can fail (e.g. if there are any columns which do not contain any data points). Use the \texttt{layer\_snap} parameter to eliminate surface blocks with very small thickness.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{data}: \texttt{np.array}\\
  Two-dimensional array of data to fit.  Each row of the array should contain the x,y,z values for each data point.  Such an array can be conveniently read from a text file using the \texttt{np.loadtxt()} method.
\item \textbf{alpha}: float\\
  Smoothing parameter for first derivatives - increasing its value results in solutions with lower gradients (but may result in extrema being smoothed out).
\item \textbf{beta}: float\\
  Smoothing parameter for second derivatives - increasing its value results in solutions with lower curvature.
\item \textbf{columns}: list of string or \hyperref[columnobjects]{\texttt{column}}\\
  Columns, or names of columns to be fitted.  If empty (the default), then all columns will be fitted.
\item \textbf{min\_columns}: list of string or \hyperref[columnobjects]{\texttt{column}}\\
  Columns, or names of columns for which elevations will be determined from the minimum of the fitted nodal elevations (elevations at all other columns are determined from the average of the fitted nodal elevations).
\item \textbf{grid\_boundary}: Boolean\\
  If \texttt{True}, test each data point first to see if it lies inside the boundary polygon of the grid.  This can speed up the fitting process if there are many data points outside the grid, and the grid has a simple boundary (e.g. a rectangle).  In general if there are many data points outside the grid, it is best to clip the data set before fitting, particularly if it is to be used more than once.
\item \textbf{layer\_snap}: float\\
  Smallest desired surface block thickness.  Set to a positive value to prevent columns being assigned surface elevations that are very close to the bottom of a layer (resulting in very thin surface blocks).  Default value is zero (i.e. no layer snapping).
\item \textbf{silent}: Boolean\\
  Set to \texttt{True} to suppress printing fitting progress.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{from\_amesh(\emph{input\_filename}='in', \emph{segment\_filename}='segmt', \emph{convention}=0, \\
      \emph{node\_tolerance}=None, \emph{justify}='r', \emph{chars}=ascii\_lowercase, \emph{spaces}=\texttt{True},\\
      \emph{block\_order}=None)}}\end{snugshade}
\label{sec:mulgrid:from_amesh}
\index{MULgraph geometry!creating!Voronoi}

Returns a \texttt{mulgrid} object (and a block mapping dictionary) from a Voronoi mesh previously created by the AMESH utility \citep{AMESH}, or by other software that uses AMESH (e.g. WinGridder or Steinar).

The block naming convention for the output \texttt{mulgrid} object can be specified via the \texttt{convention} parameter. Note that in general this may not be the same as the block naming convention of the original mesh created by AMESH. In fact, AMESH can create meshes with block naming conventions that do not correspond to any of the \hyperref[tb:mulgrid_conventions]{MULgraph conventions}. This is why the \texttt{from\_amesh()} method also returns a block mapping dictionary, which maps block names in the \texttt{mulgrid} geometry to the block names in the original AMESH grid.

The optional \texttt{justify} and \texttt{case} parameters control the formatting of the character part of the block names.  Additionally, the characters used to form node/column or layer names can be specified using the \texttt{chars} parameter.  (This can be useful for example for grids with large numbers of nodes and/or columns, for which lowercase letters alone may not be enough.)

The \texttt{from\_amesh()} method assumes the original AMESH grid has layers of constant thickness (i.e. all blocks in each layer of the AMESH input file have the same specified thickness). Grids with layers of non-constant thickness cannot be represented by a \texttt{mulgrid} object and will cause an exception to be raised.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{input\_filename}: string\\
  Filename for AMESH input file. Default is `in'.
\item \textbf{segment\_filename}: string\\
  Filename for AMESH output segment file. Default is `segmt'.
\item \textbf{convention}: integer\\
  Naming convention for grid columns and layers.
\item \textbf{node\_tolerance}: float or \texttt{None}\\
  Horizontal tolerance for identifying distinct nodes in the segment file. If a node is read in with horizontal distance from an existing node less than the tolerance, then the two nodes are assumed to be identical. If \texttt{None} (the default), then the tolerance is set to 90\% of the smallest segment length. If errors are encountered in identifying nodes belonging to the grid columns, it may be worth adjusting this parameter.
\item \textbf{justify}: string\\
  Specify `r' for the character part of the block names (first three characters) to be right-justified, `l' for left-justified.
\item \textbf{chars}: string\\
  Specify a string of characters to be used to form the character part of block names.  For example, to use both lowercase and uppercase characters, set \texttt{chars} to \texttt{ascii\_lowercase + ascii\_uppercase}, or to use uppercase letters only, specify \texttt{ascii\_uppercase}.
\item \textbf{spaces}: Boolean\\
  Specify \texttt{False} to disallow spaces in character part of block names. In this case, the first element of the \texttt{chars} parameter functions like a `zero' and replaces spaces.
\item \textbf{block\_order}: string or \texttt{None}\\
  Specify \texttt{None} or `layer\_column' for default block ordering by layer and column, starting from the atmosphere. Specify `dmplex' to order blocks by geometrical type (8-node hexahedrons first followed by 6-node wedges) as in PETSc DMPlex meshes.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{from\_gmsh(\emph{filename}, \emph{layers}, \emph{convention}=0, \emph{atmosphere\_type}=2,\\
      \emph{top\_elevation}=0, \emph{chars} = ascii\_lowercase, \emph{spaces}=\texttt{True},\\
      \emph{block\_order}=None)}}\end{snugshade}
\label{sec:mulgrid:from_gmsh}
\index{MULgraph geometry!importing from \texttt{gmsh}}

Imports a 2-D \texttt{gmsh} mesh into a geometry object.  \texttt{gmsh} is a grid generation program (see \url{http://geuz.org/gmsh/}).  The horizontal structure of the geometry object is created from the \texttt{gmsh} mesh, while the layer structure is specified via the \texttt{layers} parameter, a list of layer thicknesses.  The elevation of the top surface can also be specified, as well as the naming convention and atmosphere type.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{filename}: string\\
  Name of the \texttt{gmsh} mesh file.
\item \textbf{layers}: list\\
  List of floats containing the desired layer thicknesses.
\item \textbf{convention}: integer\\
  Naming convention for grid columns and layers.
\item \textbf{atmosphere\_type}: integer\\
  Type of atmosphere.
\item \textbf{top\_elevation}: float\\
  Elevation of the top surface of the model (default is zero).
\item \textbf{chars}: string\\
  Specifies a string of characters to use when forming the character part of block names.  Default is lowercase letters.
\item \textbf{spaces}: Boolean\\
  Specify \texttt{False} to disallow spaces in character part of block names. In this case, the first element of the \texttt{chars} parameter functions like a `zero' and replaces spaces.
\item \textbf{block\_order}: string or \texttt{None}\\
  Specify \texttt{None} or `layer\_column' for default block ordering by layer and column, starting from the atmosphere. Specify `dmplex' to order blocks by geometrical type (8-node hexahedrons first followed by 6-node wedges) as in PETSc DMPlex meshes.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{layer\_containing\_elevation(\emph{elevation})}}\end{snugshade}
\label{sec:mulgrid:layer_containing_elevation}
\index{MULgraph geometry!finding!layers}
\index{MULgraph geometry!layers!finding}

Returns the grid layer containing the specified vertical elevation.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{elevation}: float\\
  Vertical elevation.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{layer\_mapping(\emph{geo})}}\end{snugshade}
\label{sec:mulgrid:layer_mapping}

Returns a dictionary mapping each layer name in the \texttt{mulgrid} object \texttt{geo} to the name of the nearest layer in the object's own geometry.  (Note: this mapping takes no account of the grid surface, which may alter which layer is nearest in a given column.)

\textbf{Parameters:}
\begin{itemize}
\item \textbf{geo}: \hyperref[mulgrids]{\texttt{mulgrid}}\\
  The \texttt{mulgrid} object to create a layer mapping from.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{layer\_name(\emph{block\_name})}}\end{snugshade}
\label{sec:mulgrid:layer_name}
\index{MULgraph geometry!layers!names}
\index{MULgraph geometry!names!of layers}

Gives the name of the layer corresponding to the specified block name, according to the naming convention of the grid.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{block\_name}: string\\
  Block name.
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{layer\_plot(\emph{layer}, \emph{variable}=None, \emph{variable\_name}=None, \emph{unit}=None,\\
    \emph{column\_names}=None, \emph{node\_names}=None, \emph{column\_centres}=None, \emph{nodes}=None,\\
    \emph{colourmap}=None, \emph{linewidth}=0.2, \emph{linecolour}='black', \emph{aspect}='equal', \emph{plt}=None,\\
    \emph{subplot}=111, \emph{title}=None, \emph{xlabel}='x (m)', \emph{ylabel}='y (m)', \emph{contours}=False,\\
    \emph{contour\_label\_format}='\%3.0f', \emph{contour\_grid\_divisions}=(100,100),\\
    \emph{connections}=None, \emph{colourbar\_limits}=None, \emph{plot\_limits}=None, \emph{wells}=None,\\
    \emph{well\_names}=True, \emph{hide\_wells\_outside}=True, \emph{wellcolour}='blue', \\
    \emph{welllinewidth}=1.0, \emph{wellname\_bottom}=True, \emph{rocktypes}=None, \emph{allrocks}=False,\\
    \emph{rockgroup}=None, \emph{flow}=None, \emph{grid}=None, \emph{flux\_matrix}=None,\\
    \emph{flow\_variable\_name}=None, \emph{flow\_unit}=None, \emph{flow\_scale}=None,\\
    \emph{flow\_scale\_pos}=(0.5, 0.02), \emph{flow\_arrow\_width}=None, \emph{connection\_flows}=False,\\
    \emph{blockmap} = \{\}, \emph{block\_names}=None})}\end{snugshade}
\label{sec:mulgrid:layer_plot}
\index{MULgraph geometry!layers!plotting}
\index{MULgraph geometry!plotting!layers}

Plots a variable over a layer of the grid, using the \texttt{matplotlib} plotting library.  The required layer can be specified by name or as an elevation (in which case the routine will find the corresponding layer).  Specifying the layer as \texttt{None} gives a plot over the ground surface of the geometry (i.e. the surface layer for each column).

The variable can be a list or \texttt{np.array} containing a value for every block (or column) in the grid, in the order given by the \texttt{block\_name\_list} property of the geometry. If no variable is specified, only the grid in the layer is plotted, without shading.  If the variable contains a value for each column in the grid, these values are extended down each column to fill the entire grid.

The name and units of the variable can optionally be specified, and the names of the columns and nodes can also optionally be displayed on the plot, as well as the column centres (represented by crosses).  The colour map and limits of the variable shading, the line width of the grid columns and the aspect ratio of the plot can also be set, as can the title and x- and y-axis labels, and the plot limits.

When a variable is plotted over the grid, contours at specified levels can also be drawn, and optionally labelled with their values.

Well tracks can also optionally be plotted.  Each well is drawn as a line following the well track, with the well name at the bottom (or optionally the top) of the well.  For surface plots (\texttt{layer} = \texttt{None}), wells are drawn with solid lines; otherwise, wells are drawn with dotted lines except where they pass through the specified layer, where they are drawn with solid lines.

Rock types can be shown on the layer plot by specifying a \hyperref[t2grids]{\texttt{t2grid}} object as the \texttt{rocktypes} parameter.  It is possible to group similar rock types (e.g. those in the same geological formation but with slightly different permeabilities) to simplify the plot if there are a lot of rock types.

Flows can be shown on the layer by specifying an array of connection flow values (e.g mass flow) as the \texttt{flow} parameter.  Flows will then be drawn on the slice by arrows at the block centres, each representing the average flux (flow per unit area) over the block, projected onto the layer.  (For example, connection values of mass flow in kg/s will be represented as block-average mass fluxes in kg/$m^2$/s.)  Alternatively, flows through the connection faces can be plotted by setting the \texttt{connection\_flows} parameter to \texttt{True}.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{layer}: \hyperref[layerobjects]{\texttt{layer}}, string, integer, float or \texttt{None}\\
  Layer or name (string) of layer to plot, or elevation (float or integer).  Specifying \texttt{None} gives a surface plot.
\item \textbf{variable}: list (or \texttt{np.array})\\
  Variable to be plotted, of length equal to the number of blocks or columns in the grid (or \texttt{None} just to plot the grid).
\item \textbf{variable\_name}: string\\
  Name of the variable (as it will appear on the scale of the plot).
\item \textbf{unit}: string\\
  Units of the variable (as it will appear on the scale of the plot).
\item \textbf{column\_names}: Boolean or list\\
  Set to \texttt{True} if column names are to be indicated on the plot, or to a list of names of columns to be named.
\item \textbf{node\_names}: Boolean or list\\
  Set to \texttt{True} if node names are to be indicated on the plot, or to a list of names of nodes to be named.
\item \textbf{column\_centres}: Boolean or list\\
  Set to \texttt{True} if column centres are to be indicated on the plot (as crosses), or to a list of names of columns to be indicated.
\item \textbf{nodes}: Boolean or list\\
  Set to \texttt{True} if nodes are to be indicated on the plot (as crosses), or to a list of names of nodes to be indicated.
\item \textbf{colourmap}: string\\
  Name of \texttt{matplotlib} colour map to use for shading the variable.
\item \textbf{linewidth}: float\\
  Line width to use for drawing the grid.
\item \textbf{linecolour}: string\\
  Line colour to use for drawing the grid.
\item \textbf{aspect}: string\\
  Aspect ratio to use for drawing the grid (default is `equal' (i.e. 1:1).
\item \textbf{plt}: \texttt{matplotlib.pyplot} instance\\
  An instance of the \texttt{matplotlib.pyplot} library, imported in the calling script using e.g. \texttt{import matplotlib.pyplot as plt}.
\item \textbf{subplot}: integer\\
  Subplot number for multi-plots, e.g. set 223 to draw the third plot in a 2-by-2 multiplot (default is 111).
\item \textbf{title}: string\\
  Plot title.  If set to \texttt{None} (the default value), a title will be constructed from the other plot parameters.  Set to `' for no title.
\item \textbf{xlabel}: string\\
  x axis label (default is `x (m)').
\item \textbf{ylabel}: string\\
  y axis label (default is `y (m)').
\item \textbf{contours}: Boolean, list or \texttt{np.array}\\
  Set to \texttt{True} or to a list or array of contour values to draw contours on the plot (default \texttt{False}).
\item \textbf{contour\_label\_format}: string\\
  Format string for contour labels (default `\%3.0f').
\item \textbf{contour\_grid\_divisions}: tuple (of integer)\\
  Number of divisions in the x- and y-directions in the regular grid superimposed on the model grid, and used to produce the contours (default (100,100)).
\item \textbf{connections}: float (or \texttt{None})\\
  Set non-zero to plot connections in the grid, shaded by absolute value of the connection angle cosine.  The value specifies the lower cut-off value, above which connections will be plotted.  Connections are shaded in greyscale from white (0.0) to black (1.0).  This can be used to check orthogonality of grid connections, as less orthogonal connections (with larger angle cosine) will show up darker on the plot.  If set to \texttt{None}, no connections will be plotted.
\item \textbf{colourbar\_limits}: tuple, list, \texttt{np.array} (or \texttt{None})\\
  Specify a two-element tuple, list or \texttt{np.array} to set the limits of the colour scale.  Default (\texttt{None}) will auto-scale.
\item \textbf{plot\_limits}: tuple or list (or \texttt{None})\\
  Specify a two-element tuple (or list) of plot axis ranges, each itself being a tuple (or list) of minimum and maximum values, i.e. ((xmin,xmax),(ymin,ymax)).  Default is \texttt{False} which will auto-scale.
\item \textbf{wells}: Boolean or list (or \texttt{None})\\
  Specify \texttt{True} to plot all well tracks, \texttt{False} or \texttt{None} not to plot them, or a list of wells or well names to specify only particular wells.
\item \textbf{well\_names}: Boolean or list (or \texttt{None})\\
  Specify \texttt{True} to label each well with its name , \texttt{False} or \texttt{None} not to label them, or a list of wells or well names to label only particular wells.
\item \textbf{hide\_wells\_outside}: Boolean\\
  Set to \texttt{True} if wells that do not intersect the specified layer are to be hidden.
\item \textbf{wellcolour}: string\\
  Colour to use for drawing the wells.
\item \textbf{welllinewidth}: float\\
  Line width for drawing the wells.
\item \textbf{wellname\_bottom}: Boolean\\
  Set to \texttt{False} to label wells at the wellhead rather than the bottom.
\item \textbf{rocktypes}: \hyperref[t2grids]{\texttt{t2grid}} (or \texttt{None})\\
  To plot rock types, specify a \texttt{t2grid} object containing rock types for the grid.  If \texttt{None}, no rock types will be plotted.
\item \textbf{allrocks}: Boolean\\
  If \texttt{False} (the default), only rock types present on the specified layer will be shown in the colour bar; others will be omitted.  If \texttt{True}, all rocks present in the model grid will be shown on the colour bar, regardless of whether they appear in the specified layer.
\item \textbf{rockgroup}: tuple, list, string (or \texttt{None})\\
  To group similar rock types into one colour, specify a tuple or list of integers, representing the significant characters of the rock type names.  For example, to group rock types having the same first two characters, specify (0,1).  Alternatively, specify a 5-character string mask containing asterisks in positions that are not significant, and any other characters in the significant positions (e.g. `++***').
\item \textbf{flow}: \texttt{np.array} (or \texttt{None})\\
  To plot flows, specify an array of connection flow values (one floating point value for each connection in the grid).  These may for example be extracted from the columns of the connection table in a \hyperref[listingfiles]{\texttt{t2listing}} object.
\item \textbf{grid}: \hyperref[t2grids]{\texttt{t2grid}} (or \texttt{None})\\
  Specify a \texttt{t2grid} object associated with the grid, to be used to calculate the `flux matrix' which converts the connection flow values to block-average fluxes.  If this is not specified (and neither is the \texttt{flux\_matrix} parameter), then a \texttt{t2grid} object will be created internally.
\item \textbf{flux\_matrix}: \texttt{scipy.sparse.lil\_matrix} (or \texttt{None})\\
  A sparse matrix used to convert the connection flow values to block-average fluxes.  Such a matrix can be created using the \hyperref[sec:t2grid:flux_matrix]{\texttt{flux\_matrix()}} method of a \texttt{t2grid} object and an appropriate \texttt{mulgrid} object.  If no flux matrix is specified, one will be created internally.  This can be time-consuming for large grids, so for multiple flow plots it is faster to pre-calculate a flux matrix in your script and pass it via this parameter.  If this parameter is specified, there is no need also to specify the \texttt{grid} parameter.
\item \textbf{flow\_variable\_name}: string (or \texttt{None})\\
  Name of the flow variable (as it will appear on the scale of the plot).
\item \textbf{flow\_unit}: string (or \texttt{None})\\
  Units of the flow variable (as it will appear on the scale of the plot, divided by area).
\item \textbf{flow\_scale}: string (or \texttt{None})\\
  Length of flow scale arrow.  If not specified, this will be calculated.
\item \textbf{flow\_scale\_pos}: tuple\\
  Position of the flow scale on the plot, in units of dimensionless plot size.  The default (0.5, 0.02) draws the flow scale in the horizontal centre of the plot, slightly above the bottom axis.  If you want the flow scale below the bottom axis (so it doesn't get mixed up with the actual flow arrows), specify this parameter with a small negative second component, e.g. (0.8, -0.1).
\item \textbf{flow\_arrow\_width}: float (or \texttt{None})\\
  Width of the flow arrows, in units of dimensionless plot width.  If not specified, this will be calculated internally.
\item \textbf{connection\_flows}: Boolean\\
  Set to \texttt{True} to plot flows through connection faces, rather than block-averaged fluxes.  In this case, usually the \texttt{grid} parameter should also be specified (but not \texttt{flux\_matrix}), otherwise a grid will be calculated internally.
\item \textbf{blockmap}: dictionary\\
  Dictionary mapping the block names in the geometry to another block naming system. This has an effect only on the block names displayed on the plot via the \texttt{block\_names} parameter, and on the rock types displayed. Note that if a mapping is used, then the \texttt{block\_names} list should contain mapped block names.
\item \textbf{block\_names}: Boolean or list\\
  Set to \texttt{True} if block names are to be indicated on the plot, or to a list of names of blocks to be named.
\end{itemize}

\textbf{Example:}

\begin{lstlisting}
geo.layer_plot(-500., t, 'Temperature', '$\degree$C', contours = np.arange(100,200,25))
\end{lstlisting}

plots the variable \texttt{t} at elevation -500 m over the grid, with the values as Temperature ($\degree$C), and with contours drawn from 100$\degree$C to 200$\degree$C with a contour interval of 25$\degree$C.

\begin{snugshade}
\subsubsection{\texttt{line\_plot(\emph{start}=None, \emph{end}=None, \emph{variable}, \emph{variable\_name}=None,\\
\emph{unit}=None, \emph{divisions}=100, \emph{plt}=None, \emph{subplot}=111, \emph{title}='',\\
\emph{xlabel}='distance (m)', \emph{coordinate}=\texttt{False})}}\end{snugshade}
\label{sec:mulgrid:line_plot}
\index{MULgraph geometry!plotting!along a line}

Plots a variable along a line through the grid, using the \texttt{matplotlib} plotting library. The line is specified by its start and end points in 3D.  The variable can be a list or \texttt{np.array} containing a value for every block (or column) in the grid.  If the variable contains a value for each column in the grid, these values are extended down each column to fill the entire grid.  The name and units of the variable can optionally be specified, as well as the number of divisions the line is divided into (default 100), the plot title and the axis labels.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{start}, \textbf{end}: list, tuple or \texttt{np.array}\\
  Start and end point of the line, each of length 3 (\texttt{None} to plot across the bounds of the grid).
\item \textbf{variable}: list (or \texttt{np.array})\\
  Variable to be plotted, of length equal to the number of blocks (or columns) in the grid.
\item \textbf{variable\_name}: string\\
  Name of the variable (as it will appear on the scale of the plot).
\item \textbf{unit}: string\\
  Units of the variable (as it will appear on the scale of the plot).
\item \textbf{divisions}: integer\\
  Number of divisions to divide the line into (default 100).
\item \textbf{plt}: \texttt{matplotlib.pyplot} instance\\
  An instance of the \texttt{matplotlib.pyplot} library, imported in the calling script using e.g. \texttt{import matplotlib.pyplot as plt}.
\item \textbf{subplot}: integer\\
  Subplot number for multi-plots, e.g. set 223 to draw the third plot in a 2-by-2 multiplot (default is 111).
\item \textbf{title}: string\\
  Plot title.  If set to \texttt{None} (the default value), a title will be constructed from the other plot parameters.  Set to `' for no title.
\item \textbf{xlabel}: string\\
  x axis label (default is `distance (m)').
\item \textbf{coordinate}: integer or Boolean\\
  If \texttt{False}, plot against distance along the line, otherwise plot against specified coordinate (0,1 or 2) values.
\end{itemize}

\textbf{Example:}

\begin{lstlisting}
geo.line_plot([0.,0.,500.], [1000.,0.,500.], t, 'Temperature', '$\degree$C')
\end{lstlisting}

plots the variable \texttt{t} along a line from (0,0,500) to (1000,0,500) through the grid, with the values as Temperature ($\degree$C).

\begin{snugshade}\subsubsection{\texttt{line\_values(\emph{start}, \emph{end}, \emph{variable}, \emph{divisions}=100, \emph{coordinate}=\texttt{False},\\
      \emph{qtree}=None)}}\end{snugshade}
\label{sec:mulgrid:line_values}
\index{MULgraph geometry!values!along a line}

Returns values of a specified variable along an arbitrary line through the grid.  The start and end points of the line (\texttt{start} and \texttt{end}) are 3-element lists, tuples or \texttt{np.arrays} specifying points in 3D.  The variable can be a list or \texttt{np.array} containing a value for every block in the grid.  The number of divisions along the line (default 100) can be optionally specified.

The routine returns a tuple of two arrays (\emph{l},\emph{v}), the first (\emph{l}) containing the distance from the start (or the appropriate coordinate (0,1, or 2) if \texttt{coordinate} is specified) for each point along the line, and the second (\emph{v}) containing the value of the variable at that point.  The value of the variable at any point is the (block average) value at the block containing the point.

\index{MULgraph geometry!columns!quadtrees}
\index{quadtrees}

\textbf{Parameters:}
\begin{itemize}
\item \textbf{start}, \textbf{end}: list, tuple or \texttt{np.array} (of length 3)\\
  Start and end points of the line in 3D.
\item \textbf{variable}: list (or \texttt{np.array})\\
  Variable to be plotted, of length equal to the number of blocks in the grid.
\item \textbf{divisions}: integer\\
  Number of segments the line is divided up into (default 100).
\item \textbf{coordinate}: integer or Boolean\\
  If \texttt{False}, return distance along the line in first array, otherwise return specified coordinate (0,1 or 2) values.
\item \textbf{qtree}: \texttt{quadtree}\\
  Quadtree object for fast searching of grid columns (can be constructed using the \texttt{column\_quadtree()} method).
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{meshio\_grid(\emph{surface\_snap} = 0.1, \emph{dimension} = 3, \emph{slice} = \texttt{None})}}\end{snugshade}
\label{sec:mulgrid:meshio_grid}
\index{MULgraph geometry!meshio grid}

Returns mesh corresponding to the geometry, in the format used by the \texttt{meshio} library (\url{https://pypi.python.org/pypi/meshio}). This consists of a two-element tuple: firstly, an \texttt{np.array} of nodal coordinates, and secondly a dictionary of element definitions, indexed by number of nodes in the elements.

The primary use of this is as an interchange format for input/output of meshes in different formats. Note that exporting the geometry directly to a mesh file can also be done using the \hyperref[sec:mulgrid:write_mesh]{\texttt{write\_mesh()}} method (which is just a wrapper for this one).

\textbf{Parameters:}
\begin{itemize}
\item \textbf{surface\_snap}: float\\
  Tolerance for eliminating elements with very small vertical thickness at the top of the mesh.
\item \textbf{dimension}: integer\\
  Dimension of the mesh: when set to 3, return the full 3-D mesh. When set to 2, return a 2-D mesh, corresponding either to the horizontal mesh only (the default), or a vertical slice mesh if the \texttt{slice} parameter is used.
\item \textbf{slice}: list, string, float or \texttt{None}\\
  Horizontal line defining the slice for vertical 2-D meshes. This can be a list of two horizontal (\emph{x},\emph{y}) points (\texttt{np.arrays}) defining the endpoints of the slice line, or string `x' or `y' to specify the \emph{x}- or \emph{y}-axis, or northing (float) through grid centre. If set to \texttt{None} (the default) then the horizontal 2-D mesh is returned.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{minc\_array(\emph{vals}, \emph{minc\_indices}, \emph{level}=0, \emph{outside}=0.0)}}\end{snugshade}
\label{sec:mulgrid:minc_array}
\index{MULgraph geometry!MINC arrays}
\index{MINC!arrays}

Returns an array for all blocks in the geometry, with values taken from the input \texttt{vals} array, for the specified MINC level. Indexing of MINC blocks is specified by the \texttt{minc\_indices} array (returned by the \texttt{t2grid} \hyperref[sec:t2grid:MINC]{\texttt{minc()}} method).

\textbf{Parameters:}
\begin{itemize}
\item \textbf{vals}: \texttt{np.array}\\
  Array of values over the entire MINC grid, with values for all MINC levels, obtained e.g. from a column of the element table of a \hyperref[listingfiles]{\texttt{t2listing}} object.
\item \textbf{minc\_indices}: \texttt{np.array} (of integer)\\
  Rank-2 array containing integer indices for each MINC level, obtained from the output of the \texttt{t2grid} \hyperref[sec:t2grid:MINC]{\texttt{minc()}} method.
\item \textbf{level}: integer\\
  MINC level, 0 being the fracture level and higher levels being the matrix levels.
\item \textbf{outside}: Boolean or float\\
  Determines how blocks outside the MINC part of the grid are handled. If \texttt{True}, include porous medium values outside the MINC part of the grid. If a float value is given, assign that value instead. If \texttt{False}, the value zero will be assigned.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{nodes\_in\_columns(\emph{columns})}}\end{snugshade}
\label{sec:mulgrid:nodes_in_columns}
\index{MULgraph geometry!finding!nodes}
\index{MULgraph geometry!nodes!finding}

Returns a list of all nodes in a specified list of columns.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{columns}: list (of \hyperref[columnobjects]{\texttt{column}})\\
  List of columns in which to find nodes.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{nodes\_in\_polygon(\emph{polygon})}}\end{snugshade}
\label{sec:mulgrid:nodes_in_polygon}
\index{MULgraph geometry!finding!nodes}
\index{MULgraph geometry!nodes!finding}

Returns a list of all nodes inside the specified polygon or rectangle.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{polygon}: list (of \texttt{np.array})\\
  List of points defining the polygon (each point is a two-element \texttt{np.array}).  If the list has only two points, it will be interpreted as a rectangle [bottom left, top right].
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{node\_nearest\_to(\emph{point}, \emph{kdtree}=None)}}\end{snugshade}
\label{sec:mulgrid:node_nearest_to}
\index{MULgraph geometry!finding!nodes}
\index{MULgraph geometry!nodes!finding}

Returns the node nearest to a specified point.  An optional kd-tree structure can be specified to speed searching - useful if searching for many points.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{point}:  \texttt{np.array}, list or tuple\\
  Array or list of length 2, specifying the required point in 2-D.
\item \textbf{kdtree}:  \texttt{cKDTree}\\
  kd-tree structure for searching for nodes.  Such a tree can be constructed using the \texttt{node\_kdtree} property of a \texttt{mulgrid} object.  You will need the \texttt{scipy} library installed before you can use this property.
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{optimize(\emph{nodenames}=None, \emph{connection\_angle\_weight}=1.0,\\
    \emph{column\_aspect\_weight}=0.0, \emph{column\_skewness\_weight}=0.0, \emph{pest}=False)}}\end{snugshade}
\label{sec:mulgrid:optimize}
\index{MULgraph geometry!optimizing}

Adjusts positions of the specified nodes to optimize grid quality.  If no nodes are specified, all node positions are optimized.  Grid quality can be defined as a combination of connection angle cosine, column aspect ratio and column skewness.  Increasing the weight for any of these increases its importance in the evaluation of grid quality.

Note that an error will result if the connection angle weight and either of the other two weights is set to zero - in this case there are not enough constraints to fit the parameters.

If the \texttt{pest} parameter is set to \texttt{True}, the PEST parameter estimation software is used to carry out the optimzation (this obviously requires that PEST is installed on your machine).  Otherwise, the \texttt{leastsq} routine in the \texttt{scipy} Python library is used.  PEST seems to be more robust in some cases, and often gives better results when nodes on the boundary of the grid are included in the optimization. However, when \texttt{leastsq} does work satisfactorily, it is generally faster (mainly because PEST has to read the geometry from disk and write it out again each time the grid quality is evaluated during the optimization).  PEST is free software and may be downloaded from \url{http://www.pesthomepage.org/}.  If PEST is used, a variety of intermediate files (named \texttt{pestmesh.*}) will be written to the working directory, including the PEST run record file (\texttt{pestmesh.rec}) which contains a detailed record of the optimization process.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{nodenames}: list of string\\
  List of names of nodes to optimize.  If not specified, all nodes in the grid are optimized.
\item \textbf{connection\_angle\_weight}: float\\
  Weighting to be given to connection angle cosines.  A higher value will place greater priority on making connections perpendicular to the column sides.
\item \textbf{column\_aspect\_weight}: float\\
  Weighting to be given to column aspect ratios.  A higher value will place greater priority on making column side ratios closer to 1.0.
\item \textbf{column\_skewness\_weight}: float\\
  Weighting to be given to column skewness.  A higher value will place greater priority on making column angle ratios closer to 1.0.
\item \textbf{pest}: Boolean\\
  Set \texttt{True} to use the PEST parameter estimation software to perform the optimization.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{polyline\_values(\emph{polyline}, \emph{variable}, \emph{divisions}=100, \emph{coordinate}=\texttt{False},\\
      \emph{qtree}=None)}}\end{snugshade}
\label{sec:mulgrid:polyline_values}
\index{MULgraph geometry!values!along a polyline}

Returns values of a specified variable along an arbitrary polyline through the grid, defined as a list of 3-element lists or \texttt{np.arrays} specifying points in 3D.  The variable can be a list or \texttt{np.array} containing a value for every block in the grid.  The number of divisions along the line (default 100) can be optionally specified.

The routine returns a tuple of two arrays (\texttt{l},\texttt{v}), the first (\texttt{l}) containing the distance from the start (or the appropriate coordinate (0, 1, or 2) if \texttt{coordinate} is specified) for each point along the polyline, and the second (\texttt{v}) containing the value of the variable at that point.  The value of the variable at any point is the (block average) value at the block containing the point.

\index{MULgraph geometry!columns!quadtrees}
\index{quadtrees}

\textbf{Parameters:}
\begin{itemize}
\item \textbf{polyline}: list of 3-element lists or \texttt{np.arrays}\\
  Polyline points in 3D.
\item \textbf{variable}: list (or \texttt{np.array})\\
  Variable to be plotted, of length equal to the number of blocks in the grid.
\item \textbf{divisions}: integer\\
  Number of segments the line is divided up into (default 100).
\item \textbf{coordinate}: integer or Boolean\\
  If \texttt{False}, return distance along the line in first array, otherwise return specified coordinate (0, 1 or 2) values.
\item \textbf{qtree}: \texttt{quadtree}\\
  Quadtree object for fast searching of grid columns (can be constructed using the \hyperref[sec:mulgrid:column_quadtree]{\texttt{column\_quadtree()}} method).
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{read(\emph{filename})}}\end{snugshade}
\label{sec:mulgrid:read}
\index{MULgraph geometry!reading}

Reads a \texttt{mulgrid} object from a MULgraph geometry file on disk.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{filename}: string\\
  Name of the MULgraph geometry file to be read.
\end{itemize}

\textbf{Example:}

\begin{lstlisting}
geo = mulgrid().read(filename)
\end{lstlisting}

creates a \texttt{mulgrid} object and reads its contents from file \texttt{filename}.  This can be done more simply just by passing the filename into the \texttt{mulgrid} creation command:

\begin{lstlisting}
geo = mulgrid(filename)
\end{lstlisting}

\begin{snugshade}
\subsubsection{\texttt{rectangular(\emph{xblocks}, \emph{yblocks}, \emph{zblocks}, \emph{convention}=0, \emph{atmos\_type}=2,\\
    \emph{origin}=[0,0,0], \emph{justify}='r', \emph{case}=None, \emph{chars}=ascii\_lowercase,\\
    \emph{spaces}=\texttt{True}, \emph{block\_order}=None})}\end{snugshade}
\label{sec:mulgrid:rectangular}
\index{MULgraph geometry!creating!rectangular}

Gives a \texttt{mulgrid} geometry object a rectangular grid structure.  The grid sizes in the \emph{x}, \emph{y} and \emph{z} directions can be non-uniform, and the grid column and layer naming convention, atmosphere type and origin can be specified.  The optional \texttt{justify} and \texttt{case} parameters control the formatting of the character part of the block names.  Additionally, the characters used to form node/column or layer names can be specified using the \texttt{chars} parameter.  (This can be useful for example for grids with large numbers of nodes and/or columns, for which lowercase letters alone may not be enough.)

Note that it is also possible to reverse-engineer a rectangular geometry from an existing TOUGH2 data file or \texttt{t2grid} object, using the \hyperref[sec:t2grid:rectgeo]{\texttt{rectgeo()}} method.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{xblocks}, \textbf{yblocks}, \textbf{zblocks}: list, tuple or \texttt{np.array}\\
  Lists (or arrays) of block sizes (float) in the \emph{x}, \emph{y} and \emph{z} directions.
\item \textbf{convention}: integer\\
  Naming convention for grid columns and layers.
\item \textbf{atmos\_type}: integer\\
  Type of atmosphere.
\item \textbf{origin}: list (or \texttt{np.array})\\
  Origin of the grid (of length 3).
\item \textbf{justify}: string\\
  Specify `r' for the character part of the block names (first three characters) to be right-justified, `l' for left-justified.
\item \textbf{case}: string\\
  Specify `l' for the character part of the block names (first three characters) to be lower case, `u' for upper case.  Now deprecated - using the \texttt{chars} parameter is more flexible.
\item \textbf{chars}: string\\
  Specify a string of characters to be used to form the character part of block names.  For example, to use both lowercase and uppercase characters, set \texttt{chars} to \texttt{ascii\_lowercase + ascii\_uppercase}, or to use uppercase letters only, specify \texttt{ascii\_uppercase}.
\item \textbf{spaces}: Boolean\\
  Specify \texttt{False} to disallow spaces in character part of block names. In this case, the first element of the \texttt{chars} parameter functions like a `zero' and replaces spaces.
\item \textbf{block\_order}: string or \texttt{None}\\
  Specify \texttt{None} or `layer\_column' for default block ordering by layer and column, starting from the atmosphere. Specify `dmplex' to order blocks by geometrical type (8-node hexahedrons first followed by 6-node wedges) as in PETSc DMPlex meshes.
\end{itemize}

\textbf{Example:}

\begin{lstlisting}
geo = mulgrid().rectangular([1000]*10, [500]*20, [100]*5+[200]*10, origin=[0,0,2500])
\end{lstlisting}

creates a \texttt{mulgrid} object called \texttt{geo}, and fills it with a rectangular grid of 10 blocks of size 1000 m in the \emph{x}-direction, 20 blocks of size 500 m in the \emph{x}-direction, 5 layers at the top of thickness 100 m and 10 layers underneath of thickness 200 m, and with origin (0,0,2500) m.  The grid will have the default naming convention (0) and atmosphere type (2).

\begin{snugshade}\subsubsection{\texttt{reduce(\emph{columns})}}\end{snugshade}
\label{sec:mulgrid:reduce}
\index{MULgraph geometry!columns!deleting}
\index{MULgraph geometry!deleting!columns}

Reduces a grid so that it contains only the specified list of columns (or columns with specified names).

\textbf{Parameters:}
\begin{itemize}
  \item \textbf{columns}: list\\
    List of required columns or column names.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{refine(\emph{columns}=[], \emph{bisect}=False, \emph{bisect\_edge\_columns}=[],\\
    \emph{chars} = ascii\_lowercase, \emph{spaces}=\texttt{True})}}\end{snugshade}
\label{sec:mulgrid:refine}
\index{MULgraph geometry!refining!columns}
\index{MULgraph geometry!columns!refining}

Refines the specified columns in the grid.  Appropriate transition columns are created around the refined region.  If no columns are specified, all columns are refined.  All columns in the region to be refined (and in the transition region) must be either triangular or quadrilateral.  Each column in split into four, unless the \texttt{bisect} parameter is \texttt{True}, in which case each column in split into two.  If \texttt{bisect} is `x' or `y', columns are split in the closest direction to the axis specified; or if \texttt{bisect} is \texttt{True}, between its longest sides.

The \texttt{bisect\_edge\_columns} parameter can be used to give more desirable column shapes in the transition region, if the original columns occupying the transition region have large aspect ratios.  By default, these will become even worse when they are triangulated to form the transition columns, if they are connected to the refinement region by their shorter sides.  Including them in \texttt{bisect\_edge\_columns} means they will be bisected (parallel to the edge of the refinement region) before the refinement is carried out, which should improve the aspect ratios of the transition columns.

\textbf{Note}: TOUGH2 implicitly assumes that the connections in its finite volume grids are orthogonal, i.e. the line joining the centres of two connected blocks should be perpendicular to the connecting face. The triangular transition columns generated by the \texttt{refine()} method generally give rise to connections that are not orthogonal. However, they can be modified and made as orthogonal as possible using the \hyperref[sec:mulgrid:optimize]{\texttt{optimize()}} method.

\textbf{Parameters:}
\begin{itemize}
  \item \textbf{columns}: list\\
    List of columns or column names to be refined.
  \item \textbf{bisect}: Boolean or string\\
    Set to \texttt{True} if columns are to be split into two, between their longest sides, instead of four (the default).  Set to `x' or `y' to split columns along the specified axis.
  \item \textbf{bisect\_edge\_columns}: list\\
    List of columns or column names in the transition region (just outside the refinement area) to be bisected prior to the refinement, to improve the aspect ratios of the transition columns.
  \item \textbf{chars}: string\\
    Specifies a string of characters to use when forming the character part of block names.  Default is lowercase letters.
\item \textbf{spaces}: Boolean\\
  Specify \texttt{False} to disallow spaces in character part of block names. In this case, the first element of the \texttt{chars} parameter functions like a `zero' and replaces spaces.
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{refine\_layers(\emph{layers}=[], \emph{factor}=2, \emph{chars} = ascii\_lowercase, \emph{spaces}=\texttt{True})}}\end{snugshade}
\label{sec:mulgrid:refine_layers}
\index{MULgraph geometry!refining!layers}
\index{MULgraph geometry!layers!refining}

Refines the specified layers in the grid.  If no layers are specified, all layers are refined.  Each layer is refined by the specified integer factor.

\textbf{Parameters:}
\begin{itemize}
  \item \textbf{layers}: list\\
    List of layers or layer names to be refined.
  \item \textbf{factor}: integer\\
    Refinement factor: default is 2, which bisects each layer.
  \item \textbf{chars}: string\\
    Specifies a string of characters to use when forming the character part of block names.  Default is lowercase letters.
\item \textbf{spaces}: Boolean\\
  Specify \texttt{False} to disallow spaces in character part of block names. In this case, the first element of the \texttt{chars} parameter functions like a `zero' and replaces spaces.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{rename\_column(\emph{oldcolname}, \emph{newcolname})}}\end{snugshade}
\label{sec:mulgrid:rename_column}
\index{MULgraph geometry!renaming!columns}
\index{MULgraph geometry!columns!renaming}

Renames a grid column.  Returns \texttt{True} if the column was found and renamed, or \texttt{False} if the specified column does not exist.  Multiple columns can be renamed at once by specifying lists of old and new column names - this is faster than calling the method multiple times, and the block and connection name lists are updated only once.

\textbf{Parameters:}
\begin{itemize}
  \item \textbf{oldcolname}: string or list of strings\\
    Name(s) of the column(s) to rename.
  \item \textbf{newcolname}: string or list of strings\\
    New name(s) of the column(s).
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{rename\_layer(\emph{oldlayername}, \emph{newlayername})}}\end{snugshade}
\label{sec:mulgrid:rename_layer}
\index{MULgraph geometry!renaming!layers}
\index{MULgraph geometry!layers!renaming}

Renames a grid layer.  Returns \texttt{True} if the layer was found and renamed, or \texttt{False} if the specified layer does not exist.  Multiple layers can be renamed at once by specifying lists of old and new layer names - this is faster than calling the method multiple times, and the block and connection name lists are updated only once.

\textbf{Parameters:}
\begin{itemize}
  \item \textbf{oldlayername}: string or list of strings\\
    Name(s) of the layer(s) to rename.
  \item \textbf{newlayername}: string or list of strings\\
    New name(s) of the layer(s).
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{rotate(\emph{angle}, \emph{centre}=\texttt{None}, \emph{wells}=\texttt{False})}}\end{snugshade}
\label{sec:mulgrid:rotate}
\index{MULgraph geometry!rotating}

Rotates a grid by a specified angle (in degrees) clockwise in the horizontal plane.  Any wells in the grid are also rotated.  The centre of rotation can be optionally specified.  If it is not specified, the centre of the grid is used as the centre of rotation.  If the \texttt{wells} parameter is \texttt{True}, any wells in the grid are also rotated.

\textbf{Parameters:}
\begin{itemize}
  \item \textbf{angle}: float\\
    Angle (in degrees) to rotate the grid, positive for clockwise, negative for anti-clockwise.
  \item \textbf{centre}: list, tuple or \texttt{np.array}\\
    Centre of rotation in the horizontal \emph{x},\emph{y} plane (of length 2).
  \item \textbf{wells}: Boolean\\
    Set \texttt{True} to rotate wells.
\end{itemize}

\textbf{Example:}

\begin{lstlisting}
geo.rotate(30)
\end{lstlisting}

rotates the grid \texttt{geo} clockwise by 30$\degree$ about its centre in the horizontal plane.

\begin{snugshade}
\subsubsection{\texttt{slice\_plot(\emph{line}=None, \emph{variable}=None, \emph{variable\_name}=None, \emph{unit}=None,\\
    \emph{block\_names}=None, \emph{colourmap}=None, \emph{linewidth}=0.2, \emph{linecolour}='black',\\
    \emph{aspect}='auto', \emph{plt}=None, \emph{subplot}=111, \emph{title}=None, \emph{xlabel}='',\\
    \emph{ylabel}='elevation (m)', \emph{contours}=False, \emph{contour\_label\_format}='\%3.0f',\\
    \emph{contour\_grid\_divisions}=(100,100), \emph{colourbar\_limits}=None, \emph{plot\_limits}=None,\\
    \emph{column\_axis}=False, \emph{layer\_axis}=False, \emph{wells}=None, \emph{well\_names}=True,\\
    \emph{hide\_wells\_outside}=False, \emph{wellcolour}='blue', \emph{welllinewidth}=1.0,\\
    \emph{wellname\_bottom}=False, \emph{rocktypes}=None, \emph{allrocks}=False, \emph{rockgroup}=None,\\
    \emph{flow}=None, \emph{grid}=None, \emph{flux\_matrix}=None, \emph{flow\_variable\_name}=None,\\
    \emph{flow\_unit}=None, \emph{flow\_scale}=None, \emph{flow\_scale\_pos}=(0.5, 0.02),\\
    \emph{flow\_arrow\_width}=None, \emph{connection\_flows}=False, \emph{blockmap} = \{\})}}
\end{snugshade}
\label{sec:mulgrid:slice_plot}
\index{MULgraph geometry!plotting!slices}

Plots a variable over a vertical slice through the grid, using the \texttt{matplotlib} plotting library.  The required slice is specified by a horizontal line through the grid, defined as either a two-element list of (\emph{x},\emph{y}) points (\texttt{np.arrays}), or as a string `x' or `y' which defines the \emph{x}- or \emph{y}-axes respectively, or as a northing (in degrees) through the centre of the grid.  If no line is specified, the line is taken to be across the bounds of the grid.  For slice plots along the x- or y-axis, the horizontal coordinate represents the x- or y-coordinate; for other slice directions it represents distance along the slice line.

The variable can be a list or \texttt{np.array} containing a value for every block (or column) in the grid, in the order given by the \texttt{block\_name\_list} property of the geometry.  If no variable is specified, only the grid is plotted, without shading.  If the variable contains a value for each column in the grid, these values are extended down each column to fill the entire grid.

The name and units of the variable can optionally be specified, and the name of each block can also optionally be displayed on the plot.  The colour map and limits of the variable shading, the line width of the grid columns and the aspect ratio of the plot can also be set, as can the plot title and x- and z-axis labels, and the plot limits.

When a variable is plotted over the grid, contours at specified levels can also be drawn, and optionally labelled with their values.

Well tracks can also optionally be plotted.  Each well is drawn as a line following the well track, with the well name at the top (or optionally the bottom) of the well.  If \texttt{hide\_wells\_outside} is specified as a floating point number, wells that do not pass within the specified distance from the slice line are not shown.  Well tracks are shown as solid lines over sections within the specified distance from the slice line, and dotted lines otherwise.

Rock types can be shown on the slice plot by specifying a \texttt{t2grid} object as the \texttt{rocktypes} parameter.  It is possible to group similar rock types (e.g. those in the same geological formation but with slightly different permeabilities) to simplify the plot if there are a lot of rock types.

Flows can be shown on the slice by specifying an array of connection flow values (e.g mass flow) as the \texttt{flow} parameter.  Flows will then be drawn on the slice by arrows at the block centres, each representing the average flux (flow per unit area) over the block, projected onto the slice.  (For example, connection values of mass flow in kg/s will be represented as block-average mass fluxes in kg/$m^2$/s.)  Alternatively, flows through the connection faces can be plotted by setting the \texttt{connection\_flows} parameter to \texttt{True}.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{line}: list, string or float\\
  List of two horizontal (\emph{x},\emph{y}) points (\texttt{np.arrays}) defining the endpoints of the line, or string `x' or `y' to specify the \emph{x}- or \emph{y}-axis, or northing (float) through grid centre.
\item \textbf{variable}: list (or \texttt{np.array})\\
  Variable to be plotted, of length equal to the number of blocks (or columns) in the grid (or \texttt{None} just to plot the grid).
\item \textbf{variable\_name}: string\\
  Name of the variable (as it will appear on the scale of the plot).
\item \textbf{unit}: string\\
  Units of the variable (as it will appear on the scale of the plot).
\item \textbf{block\_names}: Boolean or list\\
  Set to \texttt{True} if block names are to be indicated on the plot, or to a list of names of blocks to be named.
\item \textbf{colourmap}: string\\
  Name of \texttt{matplotlib} colour map to use for shading the variable.
\item \textbf{linewidth}: float\\
  Line width to use for drawing the grid.
\item \textbf{linecolour}: string\\
  Line colour to use for drawing the grid.
\item \textbf{aspect}: string\\
  Aspect ratio to use for drawing the grid (default is `auto').
\item \textbf{plt}: \texttt{matplotlib.pyplot} instance\\
  An instance of the \texttt{matplotlib.pyplot} library, imported in the calling script using e.g. \texttt{import matplotlib.pyplot as plt}.
\item \textbf{subplot}: integer\\
  Subplot number for multi-plots, e.g. set 223 to draw the third plot in a 2-by-2 multiplot (default is 111).
\item \textbf{title}: string\\
  Plot title.  If set to \texttt{None} (the default value), a title will be constructed from the other plot parameters.  Set to `' for no title.
\item \textbf{xlabel}: string\\
  x axis label.  If set to \texttt{None} (the default value), a label will be constructed according to the slice orientation- either `x (m)', `y (m)' or `distance (m)' as appropriate.
\item \textbf{ylabel}: string\\
  y axis label (default is `elevation (m)').
\item \textbf{contours}: Boolean, list or \texttt{np.array}\\
  Set to \texttt{True} or to a list or array of contour values to draw contours on the plot (default \texttt{False}).
\item \textbf{contour\_label\_format}: string\\
  Format string for contour labels (default `\%3.0f').
\item \textbf{contour\_grid\_divisions}: tuple (of integer)\\
  Number of divisions in the x- and z-directions in the regular grid superimposed on the slice, and used to produce the contours (default (100,100)).
\item \textbf{colourbar\_limits}: tuple, list, \texttt{np.array} (or \texttt{None})\\
  Specify a two-element tuple, list or \texttt{np.array} to set the limits of the colour scale.  Default (\texttt{None}) will auto-scale.
\item \textbf{plot\_limits}: tuple or list (or \texttt{None})\\
  Specify a two-element tuple (or list) of plot axis ranges, each itself being a tuple (or list) of minimum and maximum values, i.e. ((xmin,xmax),(zmin,zmax)).  Default is \texttt{False} which will auto-scale.
\item \textbf{column\_axis}: Boolean\\
  If \texttt{True}, show column names instead of coordinates on the horizontal axis.
\item \textbf{layer\_axis}: Boolean\\
  If \texttt{True}, show layer names instead of coordinates on the vertical axis.
\item \textbf{wells}: Boolean or list (or \texttt{None})\\
  Specify \texttt{True} to plot all well tracks, \texttt{False} or \texttt{None} not to plot them, or a list of wells or well names to specify only particular wells.
\item \textbf{well\_names}: Boolean or list (or \texttt{None})\\
  Specify \texttt{True} to label each well with its name , \texttt{False} or \texttt{None} not to label them, or a list of wells or well names to label only particular wells.
\item \textbf{hide\_wells\_outside}: \texttt{False} or float\\
  Specify distance as a floating point number to hide wells further from the slice line than the specified distance.
\item \textbf{wellcolour}: string\\
  Colour to use for drawing the wells.
\item \textbf{welllinewidth}: float\\
  Line width for drawing the wells.
\item \textbf{wellname\_bottom}: Boolean\\
  Set to \texttt{True} to label wells at the bottom rather than the wellhead.
\item \textbf{rocktypes}: \hyperref[t2grids]{\texttt{t2grid}} (or \texttt{None})\\
  To plot rock types, specify a \texttt{t2grid} object containing rock types for the grid.  If \texttt{None}, no rock types will be plotted.
\item \textbf{allrocks}: Boolean\\
  If \texttt{False} (the default), only rock types present on the specified slice will be shown in the colour bar; others will be omitted.  If \texttt{True}, all rocks present in the model grid will be shown on the colour bar, regardless of whether they appear in the specified slice.
\item \textbf{rockgroup}: tuple, list, string (or \texttt{None})\\
  To group similar rock types into one colour, specify a tuple or list of integers, representing the significant characters of the rock type names.  For example, to group rock types having the same first two characters, specify (0,1).  Alternatively, specify a 5-character string mask containing asterisks in positions that are not significant, and any other characters in the significant positions (e.g. `++***').
\item \textbf{flow}: \texttt{np.array} (or \texttt{None})\\
  To plot flows, specify an array of connection flow values (one floating point value for each connection in the grid).  These may for example be extracted from the columns of the connection table in a \texttt{t2listing} object.
\item \textbf{grid}: \hyperref[t2grids]{\texttt{t2grid}} (or \texttt{None})\\
  Specify a \texttt{t2grid} object associated with the grid, to be used to calculate the `flux matrix' which converts the connection flow values to block-average fluxes.  If this is not specified (and neither is the \texttt{flux\_matrix} parameter), then a \texttt{t2grid} object will be created internally.
\item \textbf{flux\_matrix}: \texttt{scipy.sparse.lil\_matrix} (or \texttt{None})\\
  A sparse matrix used to convert the connection flow values to block-average fluxes.  Such a matrix can be created using the \texttt{flux\_matrix()} method of a \texttt{t2grid} object and an appropriate \texttt{mulgrid} object.  If no flux matrix is specified, one will be created internally.  This can be time-consuming for large grids, so for multiple flow plots it is faster to pre-calculate a flux matrix in your script and pass it via this parameter.  If this parameter is specified, there is no need also to specify the \texttt{grid} parameter.
\item \textbf{flow\_variable\_name}: string (or \texttt{None})\\
  Name of the flow variable (as it will appear on the scale of the plot).
\item \textbf{flow\_unit}: string (or \texttt{None})\\
  Units of the flow variable (as it will appear on the scale of the plot, divided by area).
\item \textbf{flow\_scale}: string (or \texttt{None})\\
  Length of flow scale arrow.  If not specified, this will be calculated.
\item \textbf{flow\_scale\_pos}: tuple\\
  Position of the flow scale on the plot, in units of dimensionless plot size.  The default (0.5, 0.02) draws the flow scale in the horizontal centre of the plot, slightly above the bottom axis.  If you want the flow scale below the bottom axis (so it doesn't get mixed up with the actual flow arrows), specify this parameter with a small negative second component, e.g. (0.8, -0.1).
\item \textbf{flow\_arrow\_width}: float (or \texttt{None})\\
  Width of the flow arrows, in units of dimensionless plot width.  If not specified, this will be calculated internally.
\item \textbf{connection\_flows}: Boolean\\
  Set to \texttt{True} to plot flows through connection faces, rather than block-averaged fluxes.  In this case, usually the \texttt{grid} parameter should also be specified (but not \texttt{flux\_matrix}), otherwise a grid will be calculated internally.
\item \textbf{blockmap}: dictionary\\
  Dictionary mapping the block names in the geometry to another block naming system. This has an effect only on the block names displayed on the plot via the \texttt{block\_names} parameter, and on the rock types displayed. Note that if a mapping is used, then the \texttt{block\_names} list should contain mapped block names.
\end{itemize}

\textbf{Example:}

\begin{lstlisting}
geo.slice_plot(45., t, 'Temperature', '$\degree$C', contours = [100,200])
\end{lstlisting}

plots the variable \texttt{t} through a SW--NE vertical slice (heading 45$\degree$) through the grid, with the values as Temperature ($\degree$C) and contours drawn at 100$\degree$C and 200$\degree$C.

\begin{lstlisting}
from matplotlib import cm
cmap = cm.get_cmap('jet', 10)
geo.slice_plot(45., t, 'Temperature', '$\degree$C',
  colourbar_limits = (0., 250.), colourmap = cmap)
\end{lstlisting}

plots the variable \texttt{t} again, but with a specified discrete colour scale with 10 divisions from zero to 250$\degree$C.

\begin{snugshade}\subsubsection{\texttt{snap\_columns\_to\_layers(\emph{min\_thickness}=1.0, \emph{columns}=[])}}\end{snugshade}
\label{sec:mulgrid:snap_columns_to_layers}
\index{MULgraph geometry!columns!surface elevation}

Snaps column surfaces to the bottom of their layers, if the surface block thickness is smaller than a given value.  This can be carried out over an optional subset of columns in the grid, otherwise over all columns.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{min\_thickness}: float\\
  Minimum surface block thickness.  Blocks with thickness less than this value will be eliminated by `snapping' the column surface elevation to the bottom of the surface layer.  Values of \texttt{min\_thickness} less than or equal to zero will have no effect.
\item \textbf{columns}: list (of \hyperref[columnobjects]{\texttt{column}} or string)\\
  List of columns to process.  If empty (the default), process all columns.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{snap\_columns\_to\_nearest\_layers(\emph{columns}=[])}}\end{snugshade}
\label{sec:mulgrid:snap_columns_to_nearest_layers}
\index{MULgraph geometry!columns!surface elevation}

Snaps column surfaces to the nearest layer elevation (top or bottom). This can be carried out over an optional subset of columns in the grid, otherwise over all columns.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{columns}: list (of \hyperref[columnobjects]{\texttt{column}} or string)\\
  List of columns to process.  If empty (the default), process all columns.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{split\_column(\emph{colname}, \emph{nodename}, \emph{chars} = ascii\_lowercase)}}\end{snugshade}
\label{sec:mulgrid:split_column}
\index{MULgraph geometry!columns!splitting}

Splits a quadrilateral column with specified name into two triangular columns.  The direction of the split is determined
by specifying the name of one of the splitting nodes.  The method returns \texttt{True} if the split was carried out successfully.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{colname}: string\\
  Name of the quadrilateral column to be split.  If the column is not quadrilateral, the method returns \texttt{False} and nothing is done to the column.
\item \textbf{nodename}: string\\
  Name of one of the splitting nodes.  The column is split across this node and the one on the opposite side of the column.  If the specified node is not in the column, the method returns \texttt{False} and nothing is done to the column.
\item \textbf{chars}: string\\
  Specifies a string of characters to use when forming the character part of block names.  Default is lowercase letters.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{translate(\emph{shift}, \emph{wells}=\texttt{False})}}\end{snugshade}
\label{sec:mulgrid:translate}
\index{MULgraph geometry!translating}

Translates a grid by a specified shift in the \emph{x}, \emph{y} and \emph{z} directions.  If the \texttt{wells} parameter is \texttt{True}, any wells in the grid are also translated.

\textbf{Parameters:}
\begin{itemize}
  \item \textbf{shift}: list, tuple or \texttt{np.array}\\
    Distance to shift the grid in the \emph{x}, \emph{y} and \emph{z} directions (of length 3).
  \item \textbf{wells}: Boolean\\\
    Set \texttt{True} to translate wells.
\end{itemize}

\textbf{Example:}

\begin{lstlisting}
geo.translate([10.e3, 0.0, -1000.0])
\end{lstlisting}

translates the grid \texttt{geo} by 10 km in the \emph{x} direction and down 1 km in the \emph{z} direction.

\begin{snugshade}
\subsubsection{\texttt{well\_values(\emph{well\_name}, \emph{variable}, \emph{divisions}=1, \emph{elevation}=\texttt{False}, \\
    \emph{deviations}=\texttt{False}, \emph{qtree}=None, \emph{extend}=\texttt{False})}}
\end{snugshade}
\label{sec:mulgrid:well_values}
\index{MULgraph geometry!values!down a well}

Returns values of a specified variable down a specified well.  The variable can be a list or \texttt{np.array} containing a value for every block in the grid.  The number of divisions between layer centres or along each well deviation (default 1) can be optionally specified (this can be increased to capture detail along a deviation that passes through several blocks).  If \texttt{deviations} is \texttt{True}, values will be returned at the nodes of the well track, instead of at grid layer centres.  If \texttt{extend} is \texttt{True}, the well trace is artificially extended to the bottom of the model.

The routine returns a tuple of two arrays (\texttt{d},\texttt{v}), the first (\texttt{d}) containing the measured depth down the well (or elevation if the \texttt{elevation} parameter is set to \texttt{True}), and the second (\texttt{v}) containing the value of the variable at each point.  The value of the variable at any point is the (block average) value at the block containing the point.

\index{MULgraph geometry!columns!quadtrees}
\index{quadtrees}

\textbf{Parameters:}
\begin{itemize}
\item \textbf{well\_name}: string\\
  Name of the well.
\item \textbf{variable}: list (or \texttt{np.array})\\
  Variable to be plotted, of length equal to the number of blocks in the grid.
\item \textbf{divisions}: integer\\
  Number of divisions each well deviation is divided up into (default 1).
\item \textbf{elevation}: Boolean\\
  Set to \texttt{True} if elevation rather than measured depth is to be returned.
\item \textbf{deviations}: Boolean\\
  Set to \texttt{True} to return values at deviation nodes, rather than intersections of layer centres with the well track.
\item \textbf{qtree}: \texttt{quadtree}\\
  Quadtree object for fast searching of grid columns (can be constructed using the \hyperref[sec:mulgrid:column_quadtree]{\texttt{column\_quadtree()}} method).
\item \textbf{extend}: Boolean\\
  Set \texttt{True} to artificially extend the well trace to the bottom of the model.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{write(\emph{filename}='')}}\end{snugshade}
\label{sec:mulgrid:write}
\index{MULgraph geometry!writing}

Writes a \texttt{mulgrid} object to a MULgraph geometry file on disk.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{filename}: string\\
  Name of the MULgraph geometry file to be written.  If no file name is specified, the object's own \texttt{filename} property is used.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{write\_bna(\emph{filename}='')}}\end{snugshade}
\label{sec:mulgrid:write_bna}
\index{MULgraph geometry!writing!BNA files}

Writes a geometry object to an Atlas BNA file on disk, for visualisation with Surfer or GIS tools.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{filename}: string\\
  Name of the BNA file to be written.  If no file name is specified, the object's own \texttt{filename} property is used, with the extension changed to *.bna.  If the object's \texttt{filename} property is not set, the default name `geometry.bna' is used.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{write\_exodusii(\emph{filename}='', \emph{arrays}=None, \emph{blockmap}=\{\})}}\end{snugshade}
\label{sec:mulgrid:write_exodusii}
\index{MULgraph geometry!writing!ExodusII files}

Writes a \texttt{mulgrid} object to an ExodusII file on disk, for visualisation or export to other software.

This method uses the VTK-Python library, so you will need that installed on your machine before you can use it. An alternative is to use the \hyperref[sec:mulgrid:write_mesh]{\texttt{write\_mesh}} method instead, which can also write meshes to ExodusII format (as well as others), and does not need the VTK-Python library (though you will need the \texttt{meshio} library).

\textbf{Parameters:}
\begin{itemize}
\item \textbf{filename}: string\\
  Name of the ExodusII file to be written.  If no file name is specified, the object's own \texttt{filename} property is used, with the extension changed to *.exo.  If the object's \texttt{filename} property is not set, the default name `geometry.exo' is used.
\item \textbf{arrays}: dictionary or \texttt{None}\\
  Data arrays to be included in the ExodusII file.  If set to \texttt{None}, default arrays (block name, layer index, column index, column area, column elevation, block number and volume) are included.
\item \textbf{blockmap}: dictionary\\
  Dictionary mapping the block names in the geometry to another block naming system.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{write\_mesh(\emph{filename}, \emph{surface\_snap} = 0.1, \emph{dimension} = 3, \emph{slice} = \texttt{None}, \\
      \emph{file\_format} = \texttt{None})}}\end{snugshade}
\label{sec:mulgrid:write_mesh}
\index{MULgraph geometry!writing!mesh files}

Writes a \texttt{mulgrid} object to a mesh file on disk, with the specific format determined by the file extension of the specified filename. This method uses the \texttt{meshio} library:

\url{https://pypi.python.org/pypi/meshio}

which must be installed on your machine, and supports various mesh output formats including Dolfin XML, ExodusII, MSH, VTK, XDMF and others. The \texttt{meshio} library may be installed from PyPI (using e.g. \texttt{pip install meshio}).

Note that many of these formats do not support columns with more than four sides.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{filename}: string\\
  Name of the mesh file to be written.
\item \textbf{surface\_snap}: float\\
  Tolerance for eliminating elements with very small vertical thickness at the top of the mesh (3-D meshes only).
\item \textbf{dimension}: integer\\
  Dimension of the mesh: when set to 3 (the default), write the full 3-D mesh. When set to 2, write a 2-D mesh, corresponding either to the horizontal mesh only (the default), or a vertical slice mesh if the \texttt{slice} parameter is used.
\item \textbf{slice}: list, string, float or \texttt{None}\\
  Horizontal line defining the slice for vertical 2-D meshes. This can be a list of two horizontal (\emph{x},\emph{y}) points (\texttt{np.arrays}) defining the endpoints of the slice line, or string `x' or `y' to specify the \emph{x}- or \emph{y}-axis, or northing (float) through grid centre. If set to \texttt{None} (the default) then the horizontal 2-D mesh is written.
\item \textbf{file\_format}: string or \texttt{None}\\
  File format for mesh output. If \texttt{None}, the file format will be decided from the filename extension (e.g. if the filename is `mesh.exo' then the mesh will be written in ExodusII format). See the \texttt{meshio} documentation for details.
\end{itemize}

\begin{snugshade}\subsubsection{\texttt{write\_vtk(\emph{filename}='', \emph{arrays}=None, \emph{wells}=False, \emph{blockmap}=\{\}, \\
      \emph{surface\_snap}=0.1)}}\end{snugshade}
\label{sec:mulgrid:write_vtk}
\index{MULgraph geometry!writing!VTK files}
\index{Visualization Tool Kit (VTK)}

Writes a \texttt{mulgrid} object to a VTK file on disk, for visualisation with VTK, Paraview, Mayavi etc.  The grid is written as an `unstructured grid' VTK object with optional data arrays defined on cells.  A separate VTK file for the wells in the grid can optionally be written.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{filename}: string\\
  Name of the VTK file to be written.  If no file name is specified, the object's own \texttt{filename} property is used, with the extension changed to *.vtu.  If the object's \texttt{filename} property is not set, the default name `geometry.vtu' is used.
\item \textbf{arrays}: dictionary or \texttt{None}\\
  Data arrays to be included in the VTK file.  If set to \texttt{None}, default arrays (block name, layer index, column index, column area, column elevation, block number and volume) are included.
\item \textbf{wells}: Boolean\\
  If set to \texttt{True}, a separate VTK file is written representing the wells in the grid.
\item \textbf{blockmap}: dictionary\\
  Dictionary mapping the block names in the geometry to another block naming system.
\item \textbf{surface\_snap}: float\\
  Tolerance for specifying how close column surface elevations need to be before being considered ``equal'' when constructing surface nodes.
\end{itemize}

\section{Other objects (\texttt{node}, \texttt{column}, \texttt{layer}, \texttt{connection} and \texttt{well})}
\label{other_mulgrid_objects}

A \texttt{mulgrid} object contains lists of other types of objects: \hyperref[nodeobjects]{\texttt{node}}, \hyperref[columnobjects]{\texttt{column}}, \hyperref[layerobjects]{\texttt{layer}}, \hyperref[connectionobjects]{\texttt{connection}} and \hyperref[wellobjects]{\texttt{well}} objects.  These classes are described below.

\subsection{\texttt{node} objects}
\label{nodeobjects}
\index{MULgraph geometry!nodes}
\index{PyTOUGH!classes!\texttt{node}}

A \texttt{node} object represents a node (i.e. vertex) in a \texttt{mulgrid} object.  A \texttt{node} object has three properties: \texttt{name}, which is a string property containing the name of the node, \texttt{pos} which is an \texttt{np.array} with three elements, containing the node's position in 3D, and \texttt{column} which is a set of the columns the node belongs to.  A \texttt{node} object does not have any methods.

A \texttt{node} object \texttt{n} can be created for example using the command \texttt{n = node(name,pos)} where \texttt{name} is the node name and pos is an \texttt{np.array} (or list, or tuple) representing the node's position.

\subsection{\texttt{column} objects}
\label{columnobjects}
\index{MULgraph geometry!columns}
\index{PyTOUGH!classes!\texttt{column}}

A \texttt{column} object represents a column in a \texttt{mulgrid} object.  The properties of a \texttt{column} object are listed in Table \ref{tb:column_properties}.

The main properties defining a column are its \texttt{name} and \texttt{node} properties.  The \texttt{name} is specified according to the naming convention of the \texttt{mulgrid} object that the column belongs to.  The \texttt{node} property is a list of \texttt{node} objects (not node names) that belong to the column.  A \texttt{column}'s \texttt{neighbour} property is a set of other \texttt{columns} connected to that column via a \texttt{connection} (see section \ref{connectionobjects}), and its \texttt{connection} property is a set of connections the column is part of.  The \texttt{neighbourlist} property is a list of neighbouring columns, with each item corresponding to a column edge (\texttt{None} if the edge is on a grid boundary).  A \texttt{column}'s \texttt{centroid} property returns the average of the positions of its vertices - which is what the \texttt{centre} property is set to, unless otherwise specified.

A \texttt{column} object has two properties measuring `grid quality'.  The \texttt{angle\_ratio} property returns the ratio of largest to smallest interior angles in the column.  The \texttt{side\_ratio} property returns the ratio of largest to smallest side lengths (a generalisation of `aspect ratio' to columns with any number of sides).  Values as close as possible to 1.0 for both these measures are desirable (their values are both exactly 1.0 for any regular polygon, e.g. an equilateral triangle or square).  Columns with large angle ratios will be highly skewed, while those with large side ratios will be typically highly elongated in one direction.

A \texttt{column} object \texttt{col} can be created for example using the command:

\begin{lstlisting}
col = column(name, nodes, centre, surface)
\end{lstlisting}

where \texttt{name} is the column name and \texttt{nodes} is a list of \hyperref[nodeobjects]{\texttt{node}} objects defining the column.  The \texttt{centre} and \texttt{surface} parameters are optional.

\texttt{column} objects have three methods, \hyperref[sec:column:contains_point]{\texttt{contains\_point}}, \hyperref[sec:column:in_polygon]{\texttt{in\_polygon}} and \hyperref[sec:column:is_against]{\texttt{is\_against}}, as described below.

\begin{snugshade}
\subsubsection{\texttt{contains\_point(\emph{pos})}}
\end{snugshade}
\label{sec:column:contains_point}
\index{MULgraph geometry!finding!columns}
\index{MULgraph geometry!columns!finding}

Returns \texttt{True} if a 2D point lies inside the column, and \texttt{False} otherwise.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{pos}: \texttt{np.array}\\
  Horizontal position of the point.
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{in\_polygon(\emph{polygon})}}
\end{snugshade}
\label{sec:column:in_polygon}
\index{MULgraph geometry!finding!columns}
\index{MULgraph geometry!columns!finding}

Returns \texttt{true} if the column centre is inside the specified polygon or rectangle.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{polygon}: list (of \texttt{np.array})\\
  List of points defining the polygon (each point is a two-element \texttt{np.array}).  If the list has only two points, it will be interpreted as a rectangle [bottom left, top right].
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{is\_against(\emph{othercolumn})}}
\end{snugshade}
\label{sec:column:is_against}

Returns \texttt{true} if the column is `against' \texttt{othercolumn} -- that is, if it shares more than one node with it.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{othercolumn}: \texttt{column})\\
  Any other column in the geometry.
\end{itemize}

\index{MULgraph geometry!columns!properties}
\begin{table}
  \begin{center}
    \begin{tabular}{|l|l|l|}
      \hline
      \textbf{Property} & \textbf{Type} & \textbf{Description}\\
      \hline
      \texttt{angle\_ratio} & float & ratio of largest to smallest interior angles \\
      \texttt{area} & float & horizontal area of the column \\
      \texttt{centre} & \texttt{np.array} & horizontal centre of the column \\
      \texttt{centroid} & \texttt{np.array} & average position of the column's vertices \\
      \texttt{connection} & set & connections the column is in \\
      \texttt{name} & string & name of the column \\
      \texttt{neighbour} & set & set of neighbouring columns \\
      \texttt{neighbourlist} & list & ordered list of neighbouring columns \\
      \texttt{node} & list & list of nodes (vertices) belonging to the column \\
      \texttt{num\_neighbours} & integer & number of neighbouring columns \\
      \texttt{num\_nodes} & integer & number of nodes belonging to the column \\
      \texttt{num\_layers} & integer & number of layers in the column below the ground surface \\
      \texttt{side\_ratio} & float & ratio of largest to smallest side length \\
      \texttt{surface} & float & surface elevation of the column (\texttt{None} if not specified)\\
      \hline
    \end{tabular}
    \caption{Properties of a \texttt{column} object}
    \label{tb:column_properties}
  \end{center}
\end{table}

\subsection{\texttt{layer} objects}
\label{layerobjects}
\index{MULgraph geometry!layers}
\index{PyTOUGH!classes!\texttt{layer}}

A \texttt{layer} object represents a layer in a \texttt{mulgrid} object. The properties of a \texttt{layer} object are given in Table \ref{tb:layer_properties}.

A \texttt{layer} object \texttt{lay} can be created for example using the command:

\begin{lstlisting}
lay = layer(name, bottom, centre, top)
\end{lstlisting}

where \texttt{name} is the layer name and \texttt{bottom}, \texttt{centre} and \texttt{top} specify the vertical position of the layer.

The methods of a \texttt{layer} object are as follows:

\begin{snugshade}
\subsubsection{\texttt{contains\_elevation(\emph{z})}}
\end{snugshade}
\index{MULgraph geometry!finding!layers}
\index{MULgraph geometry!layers!finding}

Returns \texttt{True} if a point at a given elevation lies inside the layer, and \texttt{False} otherwise.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{z}: float\\
   Elevation of the point.
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{translate(\emph{shift})}}
\end{snugshade}
\index{MULgraph geometry!layers!translating}

Translates a layer up or down by a specified distance.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{shift}: float\\
  Distance to shift the layer (positive for up, negative for down).
\end{itemize}

\index{MULgraph geometry!layers!properties}
\begin{table}
  \begin{center}
    \begin{tabular}{|l|l|l|}
      \hline
      \textbf{Property} & \textbf{Type} & \textbf{Description}\\
      \hline
      \texttt{bottom} & float & elevation of the bottom of the layer \\
      \texttt{centre} & float & elevation of the centre of the layer \\
      \texttt{thickness} & float & layer thickness (top - bottom) \\
      \texttt{top} & float & elevation of the top of the layer \\
      \texttt{name} & string & name of the layer \\
      \hline
    \end{tabular}
    \caption{Properties of a \texttt{layer} object}
    \label{tb:layer_properties}
  \end{center}
\end{table}

\subsection{\texttt{connection} objects}
\label{connectionobjects}
\index{MULgraph geometry!connections}
\index{PyTOUGH!classes!\texttt{connection}}

A \texttt{connection} object represents a connection between \texttt{columns} in a \texttt{mulgrid} object.  It has three properties: \texttt{column}, which contains a two-element list of the \texttt{column} objects making up the connection, \texttt{node}, which contains a two-element list of the \texttt{nodes} on the face joining the two columns in the connection, and \texttt{angle\_cosine}, which gives the cosine of the angle between a line joining the nodes in the connection and a line joining the centres of the two columns.  This is used as a measure of grid quality, these two lines should ideally be as close to perpendicular as possible, making the cosine of the angle zero.  A \texttt{connection} has no methods.

A \texttt{connection} object \texttt{con} can be created for example using the command

\begin{lstlisting}
con = connection(cols)
\end{lstlisting}

where \texttt{cols} is a two-element list of the \texttt{column} objects in the connection.

\subsection{\texttt{well} objects}
\label{wellobjects}
\index{MULgraph geometry!wells}
\index{PyTOUGH!classes!\texttt{well}}

A \texttt{well} object represents a well in a \texttt{mulgrid} object.  The properties of a \texttt{well} object are given in Table \ref{tb:well_properties}.

\index{MULgraph geometry!wells!properties}
\begin{table}
  \begin{center}
    \begin{tabular}{|l|l|l|}
      \hline
      \textbf{Property} & \textbf{Type} & \textbf{Description}\\
      \hline
      \texttt{bottom} & \texttt{np.array} & well bottom position \\
      \texttt{deviated} & Boolean &  whether well is deviated\\
      \texttt{head} & \texttt{np.array} & well head position \\
      \texttt{name} & string & well name \\
      \texttt{num\_deviations} & integer & number of deviations \\
      \texttt{num\_pos} & integer & number of well track nodes \\
      \texttt{pos} & list & positions (3-D arrays) of well track nodes \\
      \texttt{pos\_depth} & \texttt{np.array} & downhole depths along well track \\
      \hline
    \end{tabular}
    \caption{Properties of a \texttt{well} object}
    \label{tb:well_properties}
  \end{center}
\end{table}

The well track can be deviated, and is defined as a list \texttt{pos} of (at least two) 3D positions (\texttt{np.arrays}).  The \texttt{num\_deviations} property returns the number of deviations in the track (one less than the \texttt{num\_pos} property, which is the number of nodes in the \texttt{pos} list).  The \texttt{deviated} property returns \texttt{True} if there is more than one deviation.  The \texttt{pos\_depth} property returns an array of the downhole depths at each node along the well track.

A \texttt{well} object \texttt{w} can be created simply with the command \texttt{w = well(name,pos)}, where \texttt{name} is the well name and \texttt{pos} is a list of 3-element \texttt{np.arrays} (or lists, or tuples) representing the well trace (starting from the wellhead).

The methods of a \texttt{well} object are listed in Table \ref{tb:well_methods} and described below.

\index{MULgraph geometry!wells!methods}
\begin{table}
  \begin{center}
    \begin{tabular}{|l|l|l|}
      \hline
      \textbf{Method} & \textbf{Type} & \textbf{Description}\\
      \hline
      \hyperref[sec:well:depth_elevation]{\texttt{depth\_elevation}} & float & elevation for a given downhole depth \\
      \hyperref[sec:well:depth_pos]{\texttt{depth\_pos}} & \texttt{np.array} & position on well track for a given downhole depth \\
      \hyperref[sec:well:elevation_depth]{\texttt{elevation\_depth}} & float & downhole depth for a given elevation \\
      \hyperref[sec:well:elevation_pos]{\texttt{elevation\_pos}} & \texttt{np.array} & position on well track for a given elevation \\
      \hyperref[sec:well:pos_coordinate]{\texttt{pos\_coordinate}} & \texttt{np.array} & array of coordinates for a given index \\
      \hline
    \end{tabular}
    \caption{Methods of a \texttt{well} object}
    \label{tb:well_methods}
  \end{center}
\end{table}

\begin{snugshade}
\subsubsection{\texttt{depth\_elevation(\emph{depth})}}
\end{snugshade}
\label{sec:well:depth_elevation}
\index{MULgraph geometry!wells!depth to elevation}

Returns the elevation corresponding to the specified downhole \texttt{depth} (or \texttt{None} if \texttt{depth} is above the wellhead or below the bottom).

\textbf{Parameters:}
\begin{itemize}
\item \textbf{depth}: float\\
  Downhole depth.
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{depth\_pos(\emph{depth})}}
\end{snugshade}
\label{sec:well:depth_pos}
\index{MULgraph geometry!wells!depth to 3-D position}

Returns the 3D position of the point in the well with specified downhole \texttt{depth} (or \texttt{None} if \texttt{depth} is above the wellhead or below the bottom).  The position is interpolated between the deviation locations.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{depth}: float\\
  Downhole depth of the required point.
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{elevation\_depth(\emph{elevation})}}
\end{snugshade}
\label{sec:well:elevation_depth}
\index{MULgraph geometry!wells!elevation to depth}

Returns the downhole depth corresponding to the specified \texttt{elevation} (or \texttt{None} if \texttt{elevation} is above the wellhead or below the bottom).

\textbf{Parameters:}
\begin{itemize}
\item \textbf{elevation}: float\\
  Elevation.
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{elevation\_pos(\emph{elevation}, \emph{extend}=\texttt{False})}}
\end{snugshade}
\label{sec:well:elevation_pos}
\index{MULgraph geometry!wells!elevation to 3-D position}

Returns the 3D position of the point in the well with specified \texttt{elevation} (or \texttt{None} if \texttt{elevation} is above the wellhead or below the bottom).  The position is interpolated between the deviation locations.  If \texttt{extend} is \texttt{True}, return extrapolated positions for elevations below the bottom of the well.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{elevation}: float\\
  Elevation of the required point.
\item \textbf{extend}: Boolean\\
  If \texttt{True}, extrapolated positions will be returned for elevations below the bottom of the well (otherwise \texttt{None} will be returned).
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{pos\_coordinate(\emph{index})}}
\end{snugshade}
\label{sec:well:pos_coordinate}
\index{MULgraph geometry!wells!deviation coordinates}

Returns an \texttt{np.array} of the well track node coordinates for the given index (0, 1 or 2).  For example, \texttt{pos\_coordinate(2)} returns an array containing the elevations of all well track nodes.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{index}: integer\\
  Index required (0, 1 or 2).
\end{itemize}

\section{Other functions: block name conversions}

The \texttt{mulgrids} library contains two other functions connected with working with geometry files and TOUGH2 grids:

\begin{snugshade}
\subsubsection{\texttt{fix\_blockname(\emph{name})}}
\end{snugshade}
\label{sec:mulgrid:fix_blockname}
\index{MULgraph geometry!blocks!names}
\index{TOUGH2 grids!blocks!names}

TOUGH2 always assumes that the last two characters of a block name represent a two-digit number.  However, if that number is less than 10, the fourth character is not padded with zeros, so for example `AA101' becomes 'AA1 1' when processed by TOUGH2.

The \texttt{fix\_blockname} function corrects this by padding the fourth character of a block name with a zero if necessary.  This is only done if the third character is also a digit, e.g. when naming convention 2 is used (two characters for layer followed by three digits for column).

\textbf{Parameters:}
\begin{itemize}
\item \textbf{name}: string\\
  Block name.
\end{itemize}

\begin{snugshade}
\subsubsection{\texttt{unfix\_blockname(\emph{name})}}
\end{snugshade}
\index{MULgraph geometry!blocks!names}
\index{TOUGH2 grids!blocks!names}

This function reverses the effect of \texttt{fix\_blockname()}.

\textbf{Parameters:}
\begin{itemize}
\item \textbf{name}: string\\
  Block name.
\end{itemize}

\section{Block mappings: handling other block naming conventions}
\label{sec:mulgrid:blockmappings}
\index{TOUGH2 grids!blocks!mappings}

The MULgraph geometry format names blocks according to one of its three \hyperref[geometry_format_conventions]{naming conventions}. All of these conventions use part of the block name to indicate the layer and part of it to indicate the column.

However, in PyTOUGH it is possible to make a \texttt{mulgrid} object handle other block naming conventions by means of a \textbf{block mapping}. This is simply a dictionary that maps the block names in a \texttt{mulgrid} to block names in a \texttt{t2grid} object. The block names in the \texttt{t2grid} can follow an arbitrary convention, not based on layers and columns. For example, blocks in TOUGH2 grids created by PetraSim may be simply numbered.

A block mapping dictionary can be passed in as an optional parameter to many PyTOUGH methods that involve both a MULgraph geometry and TOUGH2 grid, for example the \texttt{mulgrid} \hyperref[sec:mulgrid:block_name]{\texttt{block\_name()}}, \hyperref[sec:mulgrid:slice_plot]{\texttt{slice\_plot()}} and \hyperref[sec:mulgrid:write_vtk]{\texttt{write\_vtk()}} methods, and the \texttt{write\_vtk()} methods of the \hyperref[sec:t2grid:write_vtk]{\texttt{t2grid}} and \hyperref[sec:t2listing:write_vtk]{\texttt{t2listing}} classes.

When the \hyperref[sec:t2grid:rectgeo]{\texttt{rectgeo()}} method is used to create a \texttt{mulgrid} object from a \texttt{t2grid}, a block mapping is also created, and may be used in the PyTOUGH methods that can accept a block mapping.

A block mapping need not contain entries for all blocks. If for example a model follows the naming convention of a MULgraph geometry in most blocks, and only a few are different, then only entries for the different block names need be present in the mapping dictionary.

Block mappings can be saved to and loaded from disk (like any other Python object) using the \texttt{pickle} library. This is part of the standard Python library collection. For example a block mapping called \texttt{blockmap} can be saved to a file called \texttt{'blockmap.pkl'} as follows:

\begin{lstlisting}
  import pickle
  pickle.dump(blockmap, file('blockmap.pkl', 'w'))
\end{lstlisting}

It can be loaded back in again like this:

\begin{lstlisting}
  blockmap = pickle.load(file('blockmap.pkl'))
\end{lstlisting}

